diff -u --recursive --new-file v2.1.131/linux/CREDITS linux/CREDITS
--- v2.1.131/linux/CREDITS	Wed Dec 16 10:32:54 1998
+++ linux/CREDITS	Tue Dec 22 08:22:07 1998
@@ -265,6 +265,14 @@
 S: Trafford, Pennsylvania 15085
 S: USA
 
+N: Dag Brattli
+E: dagb@cs.uit.no
+W: http://www.cs.uit.no/~dagb
+D: IrDA Subsystem
+S: 19. Wellington Road
+S: Lancaster, LA1 4DN
+S: UK, England
+
 N: Andries Brouwer
 E: aeb@cwi.nl
 D: random Linux hacker
@@ -338,10 +346,12 @@
 S: USA
 
 N: Juan Jose Ciarlante
+W: http://juanjox.linuxhq.com/
 E: jjciarla@raiz.uncu.edu.ar
-E: juanjo@irriga.uncu.edu.ar
+E: jjo@mendoza.gov.ar
 D: Network driver alias support
 D: IP masq hashing and app modules
+D: IP masq 2.1 features and bugs
 S: Las Cuevas 2385 - Bo Guemes
 S: Las Heras, Mendoza CP 5539
 S: Argentina
@@ -353,6 +363,11 @@
 S: East Malvern, Victoria, 3145
 S: Australia
 
+N: Neil Conway
+E: nconway.list@ukaea.org.uk
+D: Assorted sched/mm titbits
+S: Oxfordshire, UK.
+
 N: Alan Cox
 W: http://roadrunner.swansea.linux.org.uk/alan.shtml
 E: alan@lxorguk.ukuu.org.uk
@@ -435,6 +450,15 @@
 S: Socorro, New Mexico 87801
 S: USA
 
+N: Oleg Drokin
+E: green@ccssu.crimea.ua
+W: http://www.ccssu.crimea.ua/~green
+D: Cleaning up sound drivers.
+S: Skvoznoy per., 14a
+S: Evpatoria
+S: Crimea
+S: UKRAINE, 334320
+
 N: Thomas Dunbar
 E: tdunbar@vtaix.cc.vt.edu
 D: TeX & METAFONT hacking/maintenance
@@ -642,6 +666,17 @@
 S: Sterling Heights, Michigan 48313
 S: USA
 
+N: Tristan Greaves
+E: Tristan.Greaves@icl.com
+E: tmg296@ecs.soton.ac.uk
+W: http://www.ecs.soton.ac.uk/~tmg296
+D: Miscellaneous ipv4 sysctl patches
+S: 15 Little Mead
+S: Denmead
+S: Hampshire
+S: PO7 6HS
+S: United Kingdom
+
 N: Michael A. Griffith
 E: grif@cs.ucr.edu
 W: http://www.cs.ucr.edu/~grif
@@ -863,6 +898,14 @@
 S: 160 00 Praha 6
 S: Czech Republic
 
+N: Niels Kristian Bech Jensen
+E: nkbj@image.dk
+W: http://www.image.dk/~nkbj
+D: 4.4BSD and NeXTstep support in read-only ufs
+S: Dr. Holsts Vej 34, lejl. 164
+S: DK-8230 Åbyhøj
+S: Denmark
+
 N: Michael K. Johnson
 E: johnsonm@redhat.com
 W: http://www.redhat.com/~johnsonm
@@ -887,6 +930,17 @@
 S: 8103 Rein
 S: Austria
 
+N: Jan "Yenya" Kasprzak
+E: kas@fi.muni.cz
+D: Author of the COSA/SRP sync serial board driver.
+D: Port of the syncppp.c from the 2.0 to the 2.1 kernel.
+P: 1024/D3498839 0D 99 A7 FB 20 66 05 D7  8B 35 FC DE 05 B1 8A 5E
+W: http://www.fi.muni.cz/~kas/
+S: c/o Faculty of Informatics, Masaryk University
+S: Botanicka' 68a
+S: 602 00 Brno
+S: Czech Republic
+
 N: Fred N. van Kempen
 E: waltje@uwalt.nl.mugnet.org
 D: NET-2
@@ -933,6 +987,17 @@
 S: San Jose, California 95161-1311
 S: USA
 
+N: Thorsten Knabe
+E: Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
+E: Thorsten Knabe <tek01@hrzpub.tu-darmstadt.de>
+W: http://www.student.informatik.tu-darmstadt.de/~tek
+W: http://www.tu-darmstadt.de/~tek01
+P: 1024/3BC8D885 8C 29 C5 0A C0 D1 D6 F4  20 D4 2D AB 29 F6 D0 60
+D: AD1816 sound driver
+S: Am Bergfried 10
+S: 63225 Langen
+S: Germany
+
 N: Alain L. Knaff
 E: Alain.Knaff@poboxes.com
 D: floppy driver
@@ -1026,11 +1091,11 @@
 S: The Netherlands
 
 N: Volker Lendecke
-E: lendecke@namu01.Num.Math.Uni-Goettingen.de
+E: vl@kki.org
 D: Kernel smbfs (to mount WfW, NT and OS/2 network drives.)
 D: NCP filesystem support (to mount NetWare volumes)
-S: Innersteweg 11
-S: 37081 Goettingen
+S: Von Ossietzky Str. 12
+S: 37085 Goettingen
 S: Germany
 
 N: Kevin Lentin
@@ -1211,6 +1276,14 @@
 S: D-90453 Nuernberg
 S: Germany
 
+N: Arnaldo Carvalho de Melo
+E: acme@conectiva.com.br
+D: wanrouter hacking
+D: cyclades 2X sync card driver (still in early devel stage)
+S: R. Prof. Rubens Elke Braga, 558 - Parolin
+S: 80220-320 Curitiba - Parana
+S: Brazil
+
 N: Michael Meskes
 E: meskes@debian.org
 P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03  AB AB 15 A3 AE AD 39 7D
@@ -1551,7 +1624,7 @@
 
 N: Paul Russell
 E: Paul.Russell@rustcorp.com.au
-W: http://www.adelaide.net.au/~rustcorp
+W: http://www.rustcorp.com
 D: Ruggedly handsome.
 D: Developed Generic IP Firewalling Chains with Michael Neuling.
 
@@ -1591,6 +1664,11 @@
 S: B2240 Zandhoven
 S: Belgium
 
+N: Henning P. Schmiedehausen
+E: hps@tanstaafl.de
+D: added PCI support to the serial driver
+S: Buckenhof, Germany
+
 N: Martin Schulze
 E: joey@linux.de
 W: http://home.pages.de/~joey/
@@ -1950,7 +2028,8 @@
 
 N: Steven Whitehouse
 E: SteveW@ACM.org
-D: Linux DECnet project: http://eeshack3.swan.ac.uk/~gw7rrm/DECnet/index.html
+W: http://www-sigproc.eng.cam.ac.uk/~sjw44/
+D: Linux DECnet project: http://www.sucs.swan.ac.uk/~rohan/DECnet/index.html
 D: Minor debugging of other networking protocols.
 
 N: Hans-Joachim Widmaier
diff -u --recursive --new-file v2.1.131/linux/Documentation/00-INDEX linux/Documentation/00-INDEX
--- v2.1.131/linux/Documentation/00-INDEX	Wed Jun 24 22:54:01 1998
+++ linux/Documentation/00-INDEX	Fri Dec 18 14:01:48 1998
@@ -111,10 +111,10 @@
 	- how to set up linux with a serial line console as the default.
 smart-config.txt
 	- description of the Smart Config makefile feature.
-smp
-	- how to setup the kernel for SMP
 smp.tex
 	- TeX document describing implementation of Multiprocessor Linux
+smp.txt
+	- a few more notes on symmetric multi-processing
 sound/
 	- directory with info on sound card support
 specialix.txt
diff -u --recursive --new-file v2.1.131/linux/Documentation/Changes linux/Documentation/Changes
--- v2.1.131/linux/Documentation/Changes	Fri Oct 23 22:01:18 1998
+++ linux/Documentation/Changes	Wed Dec 16 12:52:00 1998
@@ -33,7 +33,7 @@
    Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
 needs.
 
-Last updated: October 9, 1998
+Last updated: December 12, 1998
 Current Author: Chris Ricker (kaboom@gatech.edu or chris.ricker@m.cc.utah.edu).
 
 Current Minimal Requirements
@@ -51,19 +51,18 @@
 - Dynamic Linker (ld.so) 1.9.9                   ; ldd --version or ldd -v
 - Linux C++ Library	 2.7.2.8                 ; ls -l /usr/lib/libg++.so.*
 - Procps		 1.2.9                   ; ps --version
-- Procinfo               14                      ; procinfo -v
+- Procinfo               15                      ; procinfo -v
 - Psmisc		 17			 ; pstree -V
-- Mount                  2.7l                    ; mount --version
-- Net-tools              1.45                    ; hostname -V
+- Net-tools              1.49                    ; hostname -V
 - Loadlin                1.6a
 - Sh-utils               1.16                    ; basename --v
-- Autofs                 0.3.11                  ; automount --version
+- Autofs                 3.1.1                   ; automount --version
 - NFS                    2.2beta37               ; showmount --version
 - Bash                   1.14.7                  ; bash -version
 - Ncpfs                  2.2.0                   ; ncpmount -v
-- Pcmcia-cs              3.0.5                   ; cardmgr -V
+- Pcmcia-cs              3.0.6                   ; cardmgr -V
 - PPP                    2.3.5                   ; pppd -v
-- PCI Utilities          1.08                    ; lspci --version
+- Util-linux             2.9                     ; chsh -v
 
 Upgrade notes
 *************
@@ -122,7 +121,7 @@
    Linux-2.1.x is ELF-only.  You can still compile a.out apps if you
 really want, but your kernel must be compiled ELF.  If you can't
 currently compile ELF, consult the ELF howto at
-http://sunsite.unc.edu/mdw/HOWTO/ELF-HOWTO.html and upgrade your system
+http://metalab.unc.edu/mdw/HOWTO/ELF-HOWTO.html and upgrade your system
 accordingly.
 
    For modules to work, you need to be running libc-5.4.x or greater.
@@ -143,8 +142,8 @@
 you're using NIS.
 
    If you upgrade to libc-5.4.46, please read and pay attention to its
-accompanying release notes.  The section about it breaking make is not
-a joke.
+accompanying release notes.  The section about it breaking make is not a
+joke.
 
 GNU libc (libc6)
 ================
@@ -225,9 +224,6 @@
    To turn on IP forwarding, issue the following command:   echo 1 >
 /proc/sys/net/ipv4/ip_forward
 
-   To run bootpd, you'll need to issue the following command:   echo 1
->/proc/sys/net/ipv4/ip_boot_agent
-
    Similar procedures are necessary to turn on other features.  If
 something appears broken, check the /proc/sys/net/ipv4/ directory.  "1"
 generally denotes enabled, while "0" generally denotes disabled.
@@ -239,11 +235,11 @@
 
    As of 2.1.102, the IP firewalling code has been replaced; ipfwadm
 will no longer work.  You need to obtain "ipchains," available from
-http://www.adelaide.net.au/~rustcorp/ipfwchains/ipfwchains.html, and use
-that instead of ipfwadm.
+http://www.rustcorp.com/linux/ipchains/ , and use that instead of
+ipfwadm.
 
-   To use port forwarding and auto forwarding you will need to obtain
-"ipmasqadm," available from http://juanjox.home.ml.org/.
+   To use masq forwarding you will need to obtain "ipmasqadm,"
+available from http://juanjox.linuxhq.com/
 
 Memory
 ======
@@ -252,16 +248,23 @@
 many memory utils, which have to be upgraded.  Get the new procps-1.2
 and you should be set.
 
-Mount and network file systems
-==============================
+Network File System
+===================
 
    The NFS code in the kernel is currently being revised, resulting in
-much-improved performance.  As a result, you'll need to upgrade mount
-to a recent 2.6 release.  Also, amd is being phased out in favor of the
-much better autofs.  You'll also have to get the appropriate utils to
-use autofs as well as the new NFS utils.  In addition, you have the
+much-improved performance.  Also, amd is being phased out in favor of
+the much better autofs.  You'll also have to get the appropriate utils
+to use autofs as well as the new NFS utils.  In addition, you have the
 choice of user-land NFS or kernel-level NFS (knfs).
 
+Util-linux (including mount)
+============================
+
+   Among other changes in the 2.1.x development, the 128 meg limit on
+IA32 swap partition sizes has been eliminated.  To use larger swap
+spaces, you need the new mkswap found in util-linux.  You also need to
+upgrade this to get the latest version of mount.
+
 RPM
 ===
 
@@ -272,7 +275,7 @@
 ======
 
    A new "stable" version of DOSEMU is available for 2.1.x kernels.
-Upgrade to 0.66.7 or later.
+Upgrade to 0.98.4 or later.
 
 Loadlin
 =======
@@ -295,7 +298,9 @@
 parallel port may no longer be where you expect it; for example, LPT1
 (under DOS) was sometimes /dev/lp1 in Linux, but will probably be
 /dev/lp0 with the new Plug-and-Play driver.  If printing breaks with
-the new driver, try checking your lpd configuration.
+the new driver, try checking your lpd configuration.  A good source of
+more information is the Documentation/parport.txt file included with
+the kernel.
 
 Setserial
 =========
@@ -331,6 +336,11 @@
    To mount SMB (Samba / Windows) shares, you'll need to use the
 smbmount utility included with recent Samba releases.
 Documentation/filesystems/smbfs.txt has more information about this.
+Note that smbmount must have been built against 2.1.x headers to work
+with 2.1.x; if all else fails, recompile it and hope it works ;-).  In
+addition, Mike Warfield has a script and some information at
+http://www.wittsend.com/mhw/smbmount.html that you will probably find
+useful.
 
 Pcmcia-cs
 =========
@@ -361,6 +371,52 @@
    fuser, which comes with psmisc, reads /proc/*/fd/* to do its job.
 Upgrade psmisc if 2.1 changes to /proc broke the version you're using.
 
+Tunelp
+======
+
+   A new version of tunelp is available which will allow you to enable
+"trustirq" mode, improving printing while using IRQ-driven lp ports.
+
+PCI utils
+=========
+
+   Linux PCI utils are available; these include lspci, which displays
+the detailed information about your system's PCI devices which used to
+be in /proc/pci, and setpci, which allws you to read and write
+configuration registers on your PCI devices.
+
+Xosview
+=======
+
+   /proc interface changes require a recent xosview.
+
+RealPlayer
+==========
+
+   Current releases of Real Player 5.0 depend on a bug in the sound
+sub-system which is no longer there.  Consequently, they don't work.
+Real is aware of the problem and should have an updated version of the
+software available shortly.  In the mean time, you can always try
+backing up your copy of rvplayer, and then editing it by:
+
+   dd if=/dev/zero of=rvplayer bs=1 count=1 seek=657586 conv=notrunc dd
+if=/dev/zero of=rvplayer bs=1 count=1 seek=665986 conv=notrunc
+
+   If you're lucky, you'll then have sound....
+
+Quotas
+======
+
+   If you are using large quotas, you should upgrade your quota utils;
+newer versions count file sizes in blocks instead of bytes, providing
+an upper limit of terabytes instead of 4 GB.
+
+Ping
+====
+
+   Most distributed ping clients are buggy.  Get an updated one from the
+iputils package.
+
 Where to get the files
 **********************
 
@@ -369,21 +425,21 @@
 
 The 2.8.1.0.23 release:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.8.1.0.23.bin.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.8.1.0.23.bin.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/binutils-2.8.1.0.23.bin.tar.gz
 Installation notes:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.8.1.0.23
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.8.1.0.23
+ftp://metalab.unc.edu/pub/Linux/GCC/release.binutils-2.8.1.0.23
 
-The 2.9.1.0.12 release:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.12-glibc.x86.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.12-libc5.x86.tar.gz
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.12.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.12-glibc.x86.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.12-libc5.x86.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.12.tar.gz
+The 2.9.1.0.15 release:
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.15-glibc.x86.tar.gz
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.15-libc5.x86.tar.gz
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/binutils-2.9.1.0.15.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.15-glibc.x86.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.15-libc5.x86.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/binutils-2.9.1.0.15.tar.gz
 Installation notes:
-ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.9.1.0.12
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.binutils-2.9.1.0.12
+ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.binutils-2.9.1.0.15
+ftp://metalab.unc.edu/pub/Linux/GCC/release.binutils-2.9.1.0.15
 
 Gnu C
 =====
@@ -391,25 +447,25 @@
 The egcs-1.0.3 release:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/egcs-1.0.3-glibc.x86.tar.bz2
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/egcs-1.0.3-libc5.x86.tar.bz2
-ftp://sunsite.unc.edu/pub/Linux/GCC/egcs-1.0.3-glibc.x86.tar.bz2
-ftp://sunsite.unc.edu/pub/Linux/GCC/egcs-1.0.3-libc5.x86.tar.bz2
+ftp://metalab.unc.edu/pub/Linux/GCC/egcs-1.0.3-glibc.x86.tar.bz2
+ftp://metalab.unc.edu/pub/Linux/GCC/egcs-1.0.3-libc5.x86.tar.bz2
 Installation notes:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.egcs-1.0.3
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.egcs-1.0.3
+ftp://metalab.unc.edu/pub/Linux/GCC/release.egcs-1.0.3
 
 Gnu C 2.7.2.3 source:
 ftp://prep.ai.mit.edu/pub/gnu/gcc-2.7.2.3.tar.gz
-ftp://sunsite.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz
+ftp://metalab.unc.edu/pub/gnu/gcc-2.7.2.3.tar.gz
 
 Linux C Library
 ===============
 
 The (libc5) 5.4.46 release:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libc-5.4.46.bin.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/libc-5.4.46.bin.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/libc-5.4.46.bin.tar.gz
 Installation notes for 5.4.46:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libc-5.4.46
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libc-5.4.46
+ftp://metalab.unc.edu/pub/Linux/GCC/release.libc-5.4.46
 
 The (libc6) GNU libc 2.0.7pre6 release:
 ftp://ftp.kernel.org/pub/software/libs/glibc/glibc-2.0.7pre6.tar.gz
@@ -420,17 +476,17 @@
 
 The 2.7.2.8 release:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/libg++-2.7.2.8.bin.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/libg++-2.7.2.8.bin.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/libg++-2.7.2.8.bin.tar.gz
 Installation notes:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/release.libg++-2.7.2.8
-ftp://sunsite.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.8
+ftp://metalab.unc.edu/pub/Linux/GCC/release.libg++-2.7.2.8
 
 Dynamic Linker
 ==============
 
 The 1.9.9 release:
 ftp://tsx-11.mit.edu/pub/linux/packages/GCC/ld.so-1.9.9.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/GCC/ld.so-1.9.9.tar.gz
+ftp://metalab.unc.edu/pub/Linux/GCC/ld.so-1.9.9.tar.gz
 
 Modules utilities
 =================
@@ -443,20 +499,20 @@
 
 The 1.2 release:
 ftp://tsx-11.mit.edu/pub/linux/sources/usr.bin/procps-1.2.9.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/system/status/ps/procps-1.2.9.tgz
+ftp://metalab.unc.edu/pub/Linux/system/status/ps/procps-1.2.9.tgz
 
 Procinfo utilities
 ==================
 
-The 14 release:
-ftp://ftp.cistron.nl/pub/people/svm/procinfo-14.tar.gz
+The 15 release:
+ftp://ftp.cistron.nl/pub/people/svm/procinfo-15.tar.gz
 
 Psmisc utilities
 ================
 
 The 17 release:
 ftp://lrcftp.epfl.ch/pub/linux/local/psmisc/psmisc-17.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/system/status/ps/psmisc-17.tar.gz
+ftp://metalab.unc.edu/pub/Linux/system/status/ps/psmisc-17.tar.gz
 
 RPM utilities
 =============
@@ -475,8 +531,8 @@
 ======
 
 The 0.98.1 release:
-ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.1.tgz
-ftp://ftp.dosemu.org/dosemu/dosemu-0.98.1.tgz
+ftp://tsx-11.mit.edu/pub/linux/ALPHA/dosemu/dosemu-0.98.4.tgz
+ftp://ftp.dosemu.org/dosemu/dosemu-0.98.4.tgz
 
 Loadlin
 =======
@@ -489,14 +545,14 @@
 ========
 
 The 1.16 release:
-ftp://sunsite.unc.edu/pub/gnu/sh-utils-1.16.tar.gz
+ftp://metalab.unc.edu/pub/gnu/sh-utils-1.16.tar.gz
 ftp://prep.ai.mit.edu/pub/gnu/sh-utils-1.16.tar.gz
 
-Mount
-=====
+Util-linux
+==========
 
-The 2.7l release:
-ftp://ftp.win.tue.nl/pub/linux/util/mount/mount-2.7l.tar.gz
+The 2.9 release:
+ftp://ftp.win.tue.nl/pub/linux/util/util-linux-2.9.tar.gz
 
 Autofs
 ======
@@ -511,22 +567,22 @@
 ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta37.tar.gz
 ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta37.tar.gz
 
-The kernel-level 9/30/98 release:
-ftp://ftp.yggdrasil.com/private/hjl/knfsd-980930.tar.gz
-ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-980930.tar.gz
+The kernel-level 12/04/98 release:
+ftp://ftp.yggdrasil.com/private/hjl/knfsd-981204.tar.gz
+ftp://ftp.kernel.org/pub/linux/devel/gcc/knfsd-981204.tar.gz
 
 Net-tools
 =========
 
-The 1.45 release:
-ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.45.tar.gz
-http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.45.tar.gz
+The 1.49 release:
+ftp://ftp.cs-ipv6.lancs.ac.uk/pub/Code/Linux/Net_Tools/net-tools-1.49.tar.gz
+http://www.tazenda.demon.co.uk/phil/net-tools/net-tools-1.49.tar.gz
 
 Ypbind
 ======
 
-The 3.2 release:
-ftp://ftp.uni-paderborn.de/pub/linux/local/yp/ypbind-3.2.tar.gz
+The 3.3 release:
+ftp://ftp.uni-paderborn.de/pub/linux/local/yp/ypbind-3.3.tar.gz
 
 Bash
 ====
@@ -534,6 +590,9 @@
 The 1.14.7 release:
 ftp://prep.ai.mit.edu/pub/gnu/bash-1.14.7.tar.gz
 
+The 2.02.1 release:
+ftp://prep.ai.mit.edu/pub/gnu/bash-2.02.1.tar.gz
+
 Ncpfs
 =====
 
@@ -544,20 +603,20 @@
 =====
 
 The 1.9.18p10 release of Samba:
-ftp://samba.anu.edu.au/pub/samba/samba-1.9.18p10.tar.gz
+ftp://ftp.samba.org/pub/samba/samba-1.9.18p10.tar.gz
 
 Pcmcia-cs
 =========
 
-The 3.0.5 release:
-ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.5.tar.gz
+The 3.0.6 release:
+ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.6.tar.gz
 
 Setserial
 =========
 
-The 2.14 release:
-ftp://tsx-11.mit.edu/pub/linux/sources/sbin/setserial-2.14.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/system/serial/setserial-2.14.tar.gz
+The 2.15 release:
+ftp://tsx-11.mit.edu/pub/linux/sources/sbin/setserial-2.15.tar.gz
+ftp://metalab.unc.edu/pub/Linux/system/serial/setserial-2.15.tar.gz
 
 PPP
 ===
@@ -568,21 +627,21 @@
 IP Chains
 =========
 
-The 1.3.3 release:
-http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.gz
-http://www.adelaide.net.au/~rustcorp/ipfwchains/ipchains-source-1.3.3.tar.bz2
+The 1.3.8 release:
+ftp://ftp.rustcorp.com/ipchains/ipchains-1.3.8.tar.gz
+ftp://ftp.rustcorp.com/ipchains/ipchains-1.3.8.tar.bz2
 
 IP Masq Adm
 ===========
 
-The 0.4.1 release:
-http://juanjox.home.ml.org/ipmasqadm-0.4.1.tar.gz
+The 0.4.2 release:
+http://juanjox.linuxhq.com/ipmasqadm-0.4.2.tar.gz
 
 iBCS
 ====
 
-The 8/30/98 release:
-ftp://tsx-11.mit.edu/pub/linux/BETA/ibcs2/ibcs-2.1-980830-ALPHA.tar.gz
+The 11/05/98 release:
+ftp://tsx-11.mit.edu/pub/linux/BETA/ibcs2/ibcs-2.1-981105-ALPHA.tar.gz
 
 Asun netatalk
 =============
@@ -593,22 +652,47 @@
 Fbset
 =====
 
-The 7/13/98 release:
-http://www.cs.kuleuven.ac.be/~geert/bin/fbset-2.0-pre-19980713.tar.gz
+The 11/04/98 release:
+http://www.cs.kuleuven.ac.be/~geert/bin/fbset-2.0-pre-19981104.tar.gz
+
+PCI utils
+=========
+
+The 1.09 release:
+ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-1.09.tar.gz
+ftp://metalab.unc.edu/pub/Linux/hardware/pciutils-1.09.tar.gz
+
+Tunelp
+======
+
+The 0-2.1.131 release:
+ftp://e-mind.com/pub/linux/tunelp/tunelp-0-2.1.131.tar.gz
+
+Xosview
+=======
+
+The 1.6.1 release:
+ftp://metalab.unc.edu/pub/Linux/system/status/xstatus/xosview-1.6.1.tar.gz
+
+Quota utils
+===========
+
+The 1.55 release:
+ftp://ftp.uk.linux.org/pub/linux/sct/quota/quota-1.55-10.i386.rpm
+ftp://ftp.uk.linux.org/pub/linux/sct/quota/quota-1.55-10.src.rpm
 
-PCIutils
+IP utils
 ========
 
-The 1.08 release:
-ftp://atrey.karlin.mff.cuni.cz/pub/linux/pci/pciutils-1.08.tar.gz
-ftp://sunsite.unc.edu/pub/Linux/hardware/pciutils-1.08.tar.gz
+The 11/01/98 release:
+ftp://ftp.inr.ac.ru/pub/ip-routing/iputils-ss981101.tar.gz
 
 Other Info
 ==========
 
    Please remember that most of these utils are available on your
 favorite local linux mirror.  If you can, please get them from a closer
-site before checking sunsite.
+site before checking metalab.
 
    You may also want to check for updated versions of this software in a
 package format for the distribution you use.
@@ -616,9 +700,9 @@
    For those of you running Red Hat (or RPM on a different
 distribution), most of these are available in RPM format.  Check around
 your favorite Red Hat mirror site before installing the non-RPM
-version.  Remember, you might need to use the -force option to get the
-upgrade to install.  ftp://ftp.redhat.com/pub/contrib/ will have almost
-everything you need, and Red Hat 5.1 ships with most necessary software.
+version.  Remember, you might need to use the --force option to get the
+upgrade to install.  ftp://contrib.redhat.com/ will have almost
+everything you need, and Red Hat 5.2 ships with most necessary software.
 
    Those of you running Debian (or a different distribution that
 supports .deb packages) can look in the "unstable" and
diff -u --recursive --new-file v2.1.131/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.1.131/linux/Documentation/Configure.help	Wed Dec 16 10:32:54 1998
+++ linux/Documentation/Configure.help	Tue Dec 22 08:29:00 1998
@@ -798,6 +798,16 @@
   called fit3.o. You must also have a high-level driver for the type
   of device that you want to support.
 
+Freecom IQ ASIC-2 protocol
+CONFIG_PARIDE_FRIQ
+  This option enables support for version 2 of the Freecom IQ parallel
+  port IDE adapter.  This adapter is used by the Maxell Superdisk 
+  drive.  If you chose to build PARIDE support into your kernel, you
+  may answer Y here to build in the protocol driver, otherwise you
+  should answer M to build it as a loadable module. The module will be
+  called friq.o. You must also have a high-level driver for the type
+  of device that you want to support. 
+
 FreeCom power protocol
 CONFIG_PARIDE_FRPW
   This option enables support for the Freecom power parallel port IDE
@@ -1767,7 +1777,7 @@
 
 Matrox Millennium support
 CONFIG_FB_MATROX_MILLENIUM
-  Say Y here if you have Matrox Millennium  or Matrox Milleninium II in 
+  Say Y here if you  have Matrox Millennium  or Matrox Millennium II in 
   the box. If you select "Advanced lowlevel driver options", you should 
   check 4 bpp packed pixel, 8 bpp packed pixel, 16 bpp packed pixel, 24
   bpp  packed pixel  and 32  bpp packed  pixel. You  can also  use font 
@@ -1783,13 +1793,10 @@
 
 Matrox G100 support
 CONFIG_FB_MATROX_G100
-  Say Y here  if you have  Matrox Productiva G100  in the box. But THIS 
-  DRIVER  IS NOT  TESTED BECAUSE  OF I  HAVE NO  G100  board  and  G100 
-  technical sheets  are top secret at this time.  But driver should not 
-  cause any damage to your computer.
-  If you select  "Advanced lowlevel  driver options",  you should check
-  8 bpp  packed pixel,  16 bpp  packed pixel,  24 bpp  packed pixel and 
-  32 bpp packed pixel. You can also use font widths different from 8.
+  Say Y  here if  you have  Matrox Productiva G100  in the box.  If you
+  select  "Advanced lowlevel  driver options",  you should  check 8 bpp
+  packed pixel,  16 bpp packed  pixel, 24 bpp  packed pixel  and 32 bpp
+  packed pixel. You can also use font widths different from 8.
 
 Matrox unified driver multihead support
 CONFIG_FB_MATROX_MULTIHEAD
@@ -7417,6 +7424,21 @@
   set, which adds the last Inuit (Greenlandic) and Sami (Lappish)
   letters that were missing in Latin 4 to cover the entire Nordic
   area.
+
+nls iso8859-15
+CONFIG_NLS_ISO8859_15
+  If you want to display filenames with native language characters
+  from the Microsoft fat filesystem family or from JOLIET CDROMs
+  correctly on the screen, you need to include the appropriate
+  input/output character sets. Say Y here for the Latin 9 character
+  set, which covers most West European languages such as Albanian,
+  Catalan, Danish, Dutch, English, Estonian, Faeroese, Finnish,
+  French, German, Galician, Irish, Icelandic, Italian, Norwegian,
+  Portuguese, Spanish, Swedish, and Valencian. Latin 9 is an update to
+  Latin 1 (ISO 8859-1) that removes a handful of rarely used
+  characters and instead adds support for Estonian, corrects the
+  support for French and Finnish, and adds the new Euro character.  If
+  unsure, say Y.
 
 nls koi8-r
 CONFIG_NLS_KOI8_R
diff -u --recursive --new-file v2.1.131/linux/Documentation/devices.txt linux/Documentation/devices.txt
--- v2.1.131/linux/Documentation/devices.txt	Tue Aug 18 22:02:01 1998
+++ linux/Documentation/devices.txt	Wed Dec 16 12:52:00 1998
@@ -98,10 +98,14 @@
 		demand.
   
     block	Floppy disks
-		  0 = /dev/fd0		First floppy disk autodetect
-		  1 = /dev/fd1		Second floppy disk autodetect
-		  2 = /dev/fd2		Third floppy disk autodetect
-		  3 = /dev/fd3		Fourth floppy disk autodetect
+		  0 = /dev/fd0		Controller 1, drive 1 autodetect
+		  1 = /dev/fd1		Controller 1, drive 2 autodetect
+		  2 = /dev/fd2		Controller 1, drive 3 autodetect
+		  3 = /dev/fd3		Controller 1, drive 4 autodetect
+		128 = /dev/fd4		Controller 2, drive 1 autodetect
+		129 = /dev/fd5		Controller 2, drive 2 autodetect
+		130 = /dev/fd6		Controller 2, drive 3 autodetect
+		131 = /dev/fd7		Controller 2, drive 4 autodetect
 
 		To specify format, add to the autodetect device number:
 		  0 = /dev/fd?		Autodetect format
diff -u --recursive --new-file v2.1.131/linux/Documentation/fb/matroxfb.txt linux/Documentation/fb/matroxfb.txt
--- v2.1.131/linux/Documentation/fb/matroxfb.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/fb/matroxfb.txt	Mon Dec 21 14:48:04 1998
@@ -0,0 +1,283 @@
+[This file is cloned from VesaFB. Thanks go to Gerd Knorr]
+
+what is matroxfb?
+=================
+
+This is a driver for a graphic framebuffer for Matrox devices on
+Alpha, Intel and PPC boxes.
+
+Advantages:
+
+ * It provides a nice large console (128 cols + 48 lines with 1024x768)
+   without using tiny, unreadable fonts.
+ * You can run XF68_FBDev on top of /dev/fb0
+ * Most important: boot logo :-)
+
+Disadvantages:
+
+ * graphic mode is slower than text mode... but you should not notice
+   if you use same resolution as you used in textmode.
+
+
+How to use it?
+==============
+
+Switching modes is done using the video=matrox:vesa=... boot parameter
+or using `fbset' program.
+
+You should compile in both vgacon (to boot if you remove you Matrox from
+box) and matroxfb (for graphics mode). You should not compile-in vesafb
+unless you have primary display on non-Matrox VBE2.0 device (see 
+Documentation/vesafb.txt for details).
+
+Currently supported video modes are (through vesa=... interface, PowerMac
+has (as addon) compatibility code.
+
+bpp | 640x400  640x480  768x576  800x600  960x720  1024x768 1152x864 1280x1024 1408x1056 1600x1200
+----+----------------------------------------------------------------------------------------------
+  4 |            0x12             0x102             0x104             0x106
+  8 |  0x100    0x101    0x180    0x103    0x188    0x105    0x190    0x107     0x198     0x11C
+ 15 |           0x110    0x181    0x113    0x189    0x116    0x191    0x119     0x199     0x11D
+ 16 |           0x111    0x182    0x114    0x18A    0x117    0x192    0x11A     0x19A     0x11E
+ 24 |           0x1B2    0x184    0x1B5    0x18C    0x1B8    0x194    0x1BB     0x19C     0x1BF
+ 32 |           0x112    0x183    0x115    0x18B    0x118    0x193    0x11B     0x19B
+
+text | 640x400  640x480  1056x344  1056x400  1056x480
+-----+------------------------------------------------
+ 8x8 |  0x1C0    0x108     0x10A     0x10B     0x10C
+8x16 | 2, 3, 7                       0x109
+
+You can enter these number either hexadecimal (leading `0x') or decimal (0x100 = 256). You can also
+use value + 512 to achieve compatibility with your old number passed to vesafb.
+
+Non-listed number can be achieved by more complicated command-line, for example
+1600x1200x32bpp can be specified by `video=matrox:vesa:0x11C,depth:32'.
+
+
+X11
+===
+
+XF68_FBDev should work just fine, but it is non-accelerated. On non-intel
+architectures there are some glitches for 24bpp videomodes. 8, 16 and 32bpp
+works fine.
+
+Running another (accelerated) X-Server like XF86_SVGA works too. But (at least)
+XFree servers have big troubles in multihead configurations (even on first
+head, not even talking about second).
+
+
+SVGALib
+=======
+
+Driver contains SVGALib compatibility code. It is turned on by choosing textual
+mode for console. You can do it at boottime by using videomode 2,3,7,0x108-0x10C 
+or 0x1C0. At runtime, `fbset -depth 0' does this work.
+Unfortunately, after SVGALib application exits, screen contents is corrupted.
+Switching to another console and back fixes it. I hope that it is SVGALib and
+not mine problem, but I'm not sure.
+
+
+Configuration
+=============
+
+You can pass kernel command line options to vesafb with
+`video=matrox:option1,option2:value2,option3' (multiple options should be 
+separated by comma, values are separated from options by `:'). 
+Accepted options:
+
+mem:X    - size of memory (X can be in megabytes, kilobytes or bytes)
+           You can only decrease value determined by driver because of
+	   it always probe for memory. Default is to use whole detected
+	   memory usable for on-screen display (i.e. max. 8MB).
+disabled - do not load driver; you can use also `off', but `disabled'
+           is here too.
+enabled  - load driver, if you have `video=matrox:disabled' in LILO configuration,
+           you can override it by this (you cannot override `off').
+	   It is default.
+noaccel  - do not use acceleration engine. It does not work on Alphas.
+accel    - use acceleration engine. It is default.
+nopan    - create initial consoles with vyres = yres, thus disabling virtual
+           scrolling.
+pan      - create initial consoles as tall as possible (vyres = memory/vxres).
+           It is default.
+nopciretry - disable PCI retries. It is needed for some broken chipsets,
+           it is autodetected for intel's 82437. In this case device does
+	   not comply to PCI 2.1 specs (it will not guarantee that every transaction
+	   terminate with success or retry in 32 PCLK).
+pciretry - enable PCI retries. It is default, except for intel's 82437.
+novga    - disables VGA I/O ports. It is default if BIOS did not enable device.
+           You should not use this option, some boards then do not restart without
+	   power off.
+vga      - preserve state of VGA I/O ports. It is default. Driver does not enable
+           VGA I/O if BIOS did not it (it is not safe to enable it in most cases).
+nobios   - disables BIOS ROM. It is default if BIOS did not enable BIOS itself.
+           You should not use this option, some boards then do not restart without
+	   power off.
+bios     - preserve state of BIOS ROM. It is default. Driver does not enable BIOS
+           if BIOS was not enabled before.
+noinit   - tells driver, that devices were already initialized. You should use it
+           if you have G100 and/or if driver cannot detect memory, you see strange
+	   pattern on screen and so on. Devices not enabled by BIOS are still
+	   initialized.
+init     - driver initializes every device it knows about. It is default.
+inv24    - change timings parameters for 24bpp modes on Millenium and Millenium II.
+           Specify this if you see strange color shadows around characters.
+noinv24  - use standard timmings. It is default.
+inverse  - invert colors on screen (for LCD displays)
+noinverse - show true colors on screen. It is default.
+dev:X    - bind driver to device X. Driver numbers device from 0 up to N, where device
+           0 is first `known' device found, 1 second and so on. lspci lists
+	   devices in this order.
+	   Default is `every' known device for driver with multihead support and
+	   first working device (usually dev:0) for driver without multihead support.
+nohwcursor - disables hardware cursor (use software cursor instead).
+hwcursor - enables hardware cursor. It is default. If you are using non-accelerated mode
+           (`noaccel' or `fbset -accel false'), software cursor is used (except for
+	   text mode).
+noblink  - disables cursor blinking. Cursor in text mode always blinks (hw limitation).
+blink    - enables cursor blinking. It is default.
+nofastfont - disables fastfont feature. It is default.
+fastfont:X - enables fastfont feature. X specifies size of memory reserved for font data,
+           it must be >= (fontwidth*fontheight*chars_in_font)/8. It is faster on
+	   Gx00 series, but slower on older cards.
+grayscale - enable grayscale summing. It works in PSEUDOCOLOR modes (text, 4bpp, 8bpp). In
+           DIRECTCOLOR modes it is limited to characters displayed through putc/putcs. Direct
+	   accesses to framebuffer can paint colors.
+nograyscale - disable grayscale summing. It is default.
+cross4MB - enables that pixel line can cross 4MB boundary. It is default for non-Millenium.
+nocross4MB - pixel line must not cross 4MB boundary. It is default for Millenium I or II,
+           because of these devices have hardware limitations which do not allow this.
+	   But this option is incompatible with some (if not all yet released) versions
+	   of XF86_FBDev.
+vesa:X   - selects startup videomode. X is number from 0 to 0x1FF, see table above
+           for detailed explanation. Default is 640x480, 8bpp if driver has 8bpp support.
+	   Otherwise first available of 640x350x4bpp, 640x480x15bpp, 640x480x24bpp,
+	   640x480x32bpp or 80x25 text (80x25 text is always available).
+If you are not satisfied with videomode selected by `vesa' option, you
+can modify it with these options:
+xres:X   - horizontal resolution, in pixels. Default is derived from `vesa' option.
+yres:X   - vertical resolution, in pixel lines. Default is derived from `vesa' option.
+upper:X  - top boundary: lines between end of VSYNC pulse and start of first pixel line 
+           of picture. Default is derived from `vesa' option.
+lower:X  - bottom boundary: lines between end of picture and start of VSYNC pulse.
+           Default is derived from `vesa' option.
+vslen:X  - length of VSYNC pulse, in lines. Default is derived from `vesa' option.
+left:X   - left boundary: pixels between end of HSYNC pulse and first pixel. Default
+           is derived from `vesa' option.
+right:X  - right boundary: pixels between end of picture and start of HSYNC pulse.
+           Default is derived from `vesa' option.
+hslen:X  - length of HSYNC pulse, in pixels. Default is derived from `vesa' option.
+pixclock:X - dotclocks, in ps (picoseconds). Default is derived from `vesa' option and
+           from `fh' and `fv' options.
+sync:X   - sync. pulse - bit 0 inverts HSYNC polarity, bit 1 VSYNC polarity.
+           If bit 3 (value 0x08) is set, composite sync instead of HSYNC is generated.
+	   If bit 5 (value 0x20) is set, sync on green is turned on.
+	   Default depends on `vesa'.
+depth:X  - Bits per pixel: 0=text, 4,8,15,16,24 or 32. Default depends on `vesa'.
+If you know capabilities of your monitor, you can specify some (or all) of `pixclk', `fh'
+and `fv'. In this case, `pixclock' is computed so that pixclock <= maxclk, real_fh <= fh
+and real_fv <= fv.
+maxclk:X - maximum dotclock. X can be specified in MHz, kHz or Hz. Default is `don't care'.
+fh:X     - maximum horizontal synchronization frequency. X can be specified in kHz or Hz.
+           Default is `don't care'.
+fv:X     - maximum vertical frequency. X must be specified in Hz. Default is 70 for modes
+           derived from `vesa' with yres <= 400, 60Hz for yres > 400.
+
+
+Limitations
+===========
+
+There are known and unknown bugs, features and misfeatures.
+Currently there are following known bugs:
+ + G100 support does not work as expected, I'm still investigating this one.
+   Using `noinit' option works, but only for `first' head :-(
+ + SVGALib does not restore screen on exit
+ + generic fbcon-cfbX procedures do not work on Alphas. Due to this,
+   `noaccel' (and cfb4 accel) driver does not work on Alpha. So everyone
+   with access to /dev/fb* on Alpha can hang machine (you should restrict
+   access to /dev/fb* - everyone with access to this device can destroy
+   your monitor, believe me...).
+ + 24bpp does not support correctly XF-FBDev on big-endian architectures.
+ + interlaced text mode is not supported; it looks like hardware limitiation,
+   but I'm not sure.
+ + maybe more...
+And following misfeatures:
+ + SVGALib does not restore screen on exit.
+ + pixclock for text modes is limited by hardware to
+    83MHz on G200
+    66MHz on Millenium I
+    60MHz on Millenium II
+   Because of I have not access to other devices, I do not know specific
+   frequencies for them. So driver does not check this and allows you to
+   set frequency higher that this. It cause sparks, black holes and other
+   pretty effects on screen. Device was not destroyed during tests :-)
+ + my Millenium G200 oscillator has frequency range from 35MHz to 380MHz
+   (and it works with 8bpp on about 320MHz dotclocks (and changed mclk)).
+   But Matrox says on product sheet that VCO limit is 50-250MHz, so I believe
+   them (maybe that chip overheates, but it has very big cooler (G100 has
+   not one), so it should work).
+ + special mixed video/graphics videomodes of Mystique and Gx00 - 2G8V16 and
+   G16V16 are not supported
+ + color keying is not supported
+ + feature connector of Mystique and Gx00 is set to VGA mode (it is disabled
+   by BIOS)
+ + DCC (monitor detection) protocol is not implemented
+ + some check for input values are not so strict how it should be (you can
+   specify vslen=4000 and so on).
+ + maybe more...
+And following features:
+ + 4bpp is available only on Millenium I and Millenium II. It is hardware
+   limitiation.
+ + current fbset is not able to set 15bpp videomode: you must specify
+   depth==16 and green.length==5. fbset does not allow you to set 
+   green.length.
+ + hardware cursor is available only in accelerated videomodes. Maybe that
+   this is misfeature and not feature.
+ + text mode uses 6 bit VGA palette instead of 8 bit (one of 262144 colors
+   instead of one of 16M colors). It is due to hardware limitation of 
+   MilleniumI/II and SVGALib compatibility.
+
+
+Benchmarks
+==========
+It is time to redraw whole screen 1000 times in 1024x768, 60Hz. It is
+time for draw 6144000 characters on screen through /dev/vcsa
+(for 32bpp it is about 3GB of data (exactly 3000 MB); for 8x16 font in 
+16 seconds, i.e. 187MBps).
+Times were obtained from one older version of driver, now they are about 3%
+faster, it is kernel-space only time on P-II/350MHz, Millenium I in 33MHz
+PCI slot, G200 in AGP 2x slot. I did not test vgacon.
+
+NOACCEL
+        8x16                 12x22
+        MilleniumI   G200    MilleniumI   G200
+8bpp    16.42         9.54   12.33         9.13
+16bpp   21.00        15.70   19.11        15.02
+24bpp   36.66        36.66   35.00        35.00
+32bpp   35.00        30.00   33.85        28.66
+
+ACCEL, nofastfont
+        8x16                 12x22                6x11
+	MilleniumI   G200    MilleniumI   G200    MilleniumI   G200
+8bpp     7.79         7.24   13.55         7.78   30.00        21.01
+16bpp    9.13         7.78   16.16         7.78   30.00        21.01
+24bpp   14.17        10.72   18.69        10.24   34.99        21.01
+32bpp   16.15	     16.16   18.73        13.09   34.99        21.01
+
+ACCEL, fastfont
+        8x16                 12x22                6x11
+	MilleniumI   G200    MilleniumI   G200    MilleniumI   G200
+8bpp     8.41         6.01    6.54         4.37   16.00        10.51
+16bpp    9.54         9.12    8.76         6.17   17.52        14.01
+24bpp   15.00        12.36   11.67        10.00   22.01        18.32
+32bpp   16.18        18.29*  12.71        12.74   24.44        21.00
+
+TEXT
+        8x16
+	MilleniumI   G200
+TEXT     3.29         1.50
+
+	
+* Yes, it is slower than Millenium I.
+--
+Petr Vandrovec <vandrove@vc.cvut.cz>
diff -u --recursive --new-file v2.1.131/linux/Documentation/memory.txt linux/Documentation/memory.txt
--- v2.1.131/linux/Documentation/memory.txt	Wed Jan 15 18:46:06 1997
+++ linux/Documentation/memory.txt	Tue Dec 22 08:31:07 1998
@@ -18,13 +18,9 @@
 	   as you add more memory.  Consider exchanging your 
            motherboard.
 
-	4) Linux will not currently detect above 64M of RAM, 
-	   regardless of how much memory is actually installed.
-
 All of these problems can be addressed with the "mem=XXXM" boot option
-(where XXX is the size of RAM to use in megabytes).  Adding this boot
-option to your boot loader can help Linux see more than 64M.  It can
-also tell Linux to use less memory than is actually installed.
+(where XXX is the size of RAM to use in megabytes).  
+It can also tell Linux to use less memory than is actually installed.
 
 See the documentation of your boot loader (LILO, loadlin, etc.) about
 how to pass options to the kernel.
diff -u --recursive --new-file v2.1.131/linux/Documentation/networking/ip-sysctl.txt linux/Documentation/networking/ip-sysctl.txt
--- v2.1.131/linux/Documentation/networking/ip-sysctl.txt	Thu May 14 19:47:37 1998
+++ linux/Documentation/networking/ip-sysctl.txt	Fri Dec 18 09:36:05 1998
@@ -123,6 +123,12 @@
 	0 to disable any limiting, otherwise the maximal rate in jiffies(1)
 	See the source for more information.
 
+icmp_ignore_bogus_error_responses - BOOLEAN
+	Some routers violate RFC 1122 by sending bogus responses to broadcast
+	frames.  Such violations are normally logged via a kernel warning.
+	If this is set to TRUE, the kernel will not give such warnings, which
+	will avoid log file clutter.
+	Default: FALSE
 
 (1) Jiffie: internal timeunit for the kernel. On the i386 1/100s, on the
 Alpha 1/1024s. See the HZ define in /usr/include/asm/param.h for the exact
diff -u --recursive --new-file v2.1.131/linux/Documentation/networking/irda.txt linux/Documentation/networking/irda.txt
--- v2.1.131/linux/Documentation/networking/irda.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/networking/irda.txt	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,13 @@
+To use the IrDA protocols within Linux you will need to get a suitable copy
+of the IrDA Utilities. More detailed information about these and associated
+programs can be found on http://www.cs.uit.no/~dagb/irda/.
+
+For more information about the IrDA protocol stack, see the IR-HOWTO
+written by Werner Heuser <r2d2c3po@zedat.fu-berlin.de>
+
+There is an active mailing list for discussing Linux IrDA matters called
+linux-irda. To subscribe to it, send a message to Majordomo@list.uit.no
+with the words "subscribe linux-irda" in the body of the message, the
+subject field is ignored.
+
+Dag Brattli <dagb@cs.uit.no>
diff -u --recursive --new-file v2.1.131/linux/Documentation/paride.txt linux/Documentation/paride.txt
--- v2.1.131/linux/Documentation/paride.txt	Mon Oct  5 13:13:35 1998
+++ linux/Documentation/paride.txt	Tue Dec 22 08:29:00 1998
@@ -42,6 +42,7 @@
 	SyQuest EZ-135, EZ-230 & SparQ drives
 	Avatar Shark
 	Imation Superdisk LS-120
+	Maxell Superdisk LS-120
 	FreeCom Power CD 
 	Hewlett-Packard 5GB and 8GB tape drives
 	Hewlett-Packard 7100 and 7200 CD-RW drives
@@ -76,6 +77,7 @@
         epia    Shuttle EPIA                           (UK)
 	fit2    FIT TD-2000			       (US)
 	fit3    FIT TD-3000			       (US)
+	friq    Freecom IQ cable                       (DE)
         frpw    Freecom Power                          (DE)
         kbic    KingByte KBIC-951A and KBIC-971A       (TW)
 	ktti    KT Technology PHd adapter              (SG)
@@ -111,10 +113,12 @@
 	MicroSolutions          8000t tape      pt      bpck
 	SyQuest			EZ, SparQ	pd	epat
 	Imation			Superdisk	pf	epat
+	Maxell                  Superdisk       pf      friq
 	Avatar			Shark		pd	epat
 	FreeCom			CD-ROM		pcd	frpw
 	Hewlett-Packard		5GB Tape	pt	epat
-	Hewlett-Packard		7100/7200	pg	epat
+	Hewlett-Packard		7200e (CD)	pcd	epat
+	Hewlett-Packard		7200e (CD-R)	pg	epat
 
 2.1  Configuring built-in drivers
 
@@ -299,7 +303,6 @@
 partitioned.  Consequently, the pf driver does not support partitioned
 media.  This may be changed in a future version of the driver. 
 
-
 2.5  Using the pt driver
 
 The pt driver for parallel port ATAPI tape drives is a minimal driver.
@@ -307,27 +310,29 @@
 For best performance, a block size of 32KB should be used.  You will
 probably want to set the parallel port delay to 0, if you can.
 
-
 2.6  Using the pg driver
 
 The pg driver can be used in conjunction with the cdrecord program
-to create CD-ROMs.  Please get cdrecord version 1.6.1a3 or later
-from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ (you may have to look
-in the alpha subdirectory).  To record CD-R media your parallel port
-should ideally be set to EPP mode, and the "port delay" should be
-set to 0.  With those settings it is possible to record at 2x speed
-without any buffer underruns.  If you cannot get the driver to work
+to create CD-ROMs.  Please get cdrecord version 1.6.1 or later
+from ftp://ftp.fokus.gmd.de/pub/unix/cdrecord/ .  To record CD-R media 
+your parallel port should ideally be set to EPP mode, and the "port delay" 
+should be set to 0.  With those settings it is possible to record at 2x 
+speed without any buffer underruns.  If you cannot get the driver to work
 in EPP mode, try to use "bidirectional" or "PS/2" mode and 1x speeds only.
 
 
 3. Troubleshooting
 
+3.1  Use EPP mode if you can
+
 The most common problems that people report with the PARIDE drivers
 concern the parallel port CMOS settings.  At this time, none of the
 PARIDE protocol modules support ECP mode, or any ECP combination modes.
 If you are able to do so, please set your parallel port into EPP mode
 using your CMOS setup procedure.
 
+3.2  Check the port delay
+
 Some parallel ports cannot reliably transfer data at full speed.  To
 offset the errors, the PARIDE protocol modules introduce a "port
 delay" between each access to the i/o ports.  Each protocol sets
@@ -341,6 +346,25 @@
 read the comments at the beginning of the driver source files in
 linux/drivers/block/paride.
 
+3.3  Some drives need a printer reset
+
+There appear to be a number of "noname" external drives on the market
+that do not always power up correctly.  We have noticed this with some
+drives based on OnSpec and older Freecom adapters.  In these rare cases,
+the adapter can often be reinitialised by issuing a "printer reset" on
+the parallel port.  As the reset operation is potentially disruptive in 
+multiple device environments, the PARIDE drivers will not do it 
+automatically.  You can however, force a printer reset by doing:
+
+	insmod lp
+	rmmod lp
+
+If you have one of these marginal cases, you should probably build
+your paride drivers as modules, and arrange to do the printer reset
+before loading the PARIDE drivers. 
+
+3.4  Use the verbose option and dmesg if you need help
+
 While a lot of testing has gone into these drivers to make them work
 as smoothly as possible, problems will arise.  If you do have problems,
 please check all the obvious things first:  does the drive work in
@@ -368,6 +392,8 @@
 of two ways.  Either send it directly to the author of the PARIDE suite,
 by e-mail to grant@torque.net, or join the linux-parport mailing list
 and post your report there.
+
+3.5  For more information or help
 
 You can join the linux-parport mailing list by sending a mail message
 to 
diff -u --recursive --new-file v2.1.131/linux/Documentation/smp linux/Documentation/smp
--- v2.1.131/linux/Documentation/smp	Sat May  2 14:19:52 1998
+++ linux/Documentation/smp	Wed Dec 31 16:00:00 1969
@@ -1,23 +0,0 @@
-To set up SMP
-
-Edit linux/Makefile and uncomment SMP=1, then compile and install
-as usual.
-
-If you are using LILO, it is handy to have both SMP and non-SMP
-kernel images on hand. Edit /etc/lilo.conf to create an entry
-for another kernel image called "linux-smp" or something.
-
-The next time you compile the kernel, when running a SMP kernel,
-edit linux/Makefile and change "MAKE=make" to "MAKE=make -jN"
-(where N = number of CPU + 1, or if you have tons of memory/swap
- you can just use "-j" without a number). Feel free to experiment
-with this one.
-
-Of course you should time how long each build takes :-)
-Example:
-   make config
-   time -v sh -c 'make dep ; make clean install modules modules_install'
-
-If you are using some Compaq MP compliant machines you will need to set
-the operating system in the BIOS settings to "Unixware" - don't ask me
-why Compaqs don't work otherwise.
diff -u --recursive --new-file v2.1.131/linux/Documentation/smp.txt linux/Documentation/smp.txt
--- v2.1.131/linux/Documentation/smp.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/smp.txt	Fri Dec 18 14:01:48 1998
@@ -0,0 +1,22 @@
+To set up SMP
+
+Configure the kernel and answer Y to CONFIG_SMP.
+
+If you are using LILO, it is handy to have both SMP and non-SMP
+kernel images on hand. Edit /etc/lilo.conf to create an entry
+for another kernel image called "linux-smp" or something.
+
+The next time you compile the kernel, when running a SMP kernel,
+edit linux/Makefile and change "MAKE=make" to "MAKE=make -jN"
+(where N = number of CPU + 1, or if you have tons of memory/swap
+ you can just use "-j" without a number). Feel free to experiment
+with this one.
+
+Of course you should time how long each build takes :-)
+Example:
+   make config
+   time -v sh -c 'make dep ; make clean install modules modules_install'
+
+If you are using some Compaq MP compliant machines you will need to set
+the operating system in the BIOS settings to "Unixware" - don't ask me
+why Compaqs don't work otherwise.
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/AD1816 linux/Documentation/sound/AD1816
--- v2.1.131/linux/Documentation/sound/AD1816	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/AD1816	Wed Dec 16 12:52:00 1998
@@ -0,0 +1,118 @@
+Documentation for the AD1816(A) sound driver
+============================================
+
+NOTE: This driver is still EXPERIMENTAL, so don't use it on production
+systems!
+
+
+Installation:
+-------------
+
+To get your AD1816(A) based sound card work, you'll have to enable
+module support ("Enable loadable module support") and support for
+experimental code ("Prompt for development and/or incomplete
+code/drivers") during kernel configuration. Enable "Sound card
+support", "OSS modules support" and "Support for AD1816(A) based cards
+(EXPERIMENTAL)" in the sound configuration menu, too. Be sure, that
+you build "Support for AD1816(A) based cards (EXPERIMENTAL)" as a MODULE,
+otherwise you may run into problems later.
+Now build, install and reboot the new kernel as usual.
+
+Since the AD1816(A) is a P'n'P sound chip you'll usually have to
+configure it using the isapnptools. See isapnptools documentation for
+details on configuring P'n'P cards.
+
+After you have successfully configured the card using isapnp, you may
+load the AD1816 driver using modprobe. A typical modprobe call should
+look like this:
+
+  modprobe ad1816 io=0x530 irq=5 dma=1 dma2=3 ad1816_clockfreq=33000
+
+if your isapnp.conf file looks like this (relevant lines only):
+
+ (INT 0 (IRQ 5 (MODE +E)))
+ (DMA 0 (CHANNEL 1))
+ (DMA 1 (CHANNEL 3))
+ (IO 0 (BASE 0x0220))
+ (IO 1 (BASE 0x0388))
+ (IO 2 (BASE 0x0530))
+
+NOTE: Be sure, that you use the address IO 2 (in our example 0x530) when
+loading the module!
+
+If your setup was correct, you should see the following messages in  
+/var/log/messages (numbers may be different):
+
+Nov  6 17:07:26 tek01 kernel: ad1816_detect(530)
+Nov  6 17:07:26 tek01 kernel: ad1816_detect() - Detected OK
+Nov  6 17:07:26 tek01 kernel: AD1816 Version: 3
+
+
+Features:
+---------
+
+List of features supported by this driver:
+- full-duplex support
+- supported audio formats: unsigned 8bit, signed 16bit little endian, 
+                           signed 16bit big endian, µ-law, A-law
+- supported channels: mono and stereo
+- supported recording sources: Master, CD, Line, Line1, Line2, Mic
+- supports phat 3d stereo circuit (Line 3)
+
+
+Supported cards:
+----------------
+
+The following cards are known to work with this driver:
+- Terratec Base 1 
+- Terratec Base 64 
+- HP Kayak 
+- Acer FX-3D
+- SY-1816 
+- Highscreen Sound-Boostar 32 Wave 3D
+- ...
+
+
+Troubleshooting:
+----------------
+
+First of all you should check, if the driver has been loaded
+properly. If you get the following message in your /var/log/messages:
+
+Nov  6 17:06:31 tek01 kernel: ad1816_detect(530)
+Nov  6 17:06:31 tek01 kernel: Chip is not an AD1816 or chip is not active 
+
+you either used the wrong address for loading the driver, your chip is
+not an AD1816 or you forgot to initialize the card with isapnp.
+
+If loading of the driver succeeds, but playback/capture fails, check
+if you used the correct values for irq, dma and dma2 when loading the module.
+If one of them is wrong you usually get the following error message:
+
+Nov  6 17:06:13 tek01 kernel: Sound: DMA (output) timed out - IRQ/DRQ config error?
+
+If playback/capture is too fast or to slow, you should have a look at
+the clock chip of your sound card. The AD1816 was designed for a 33MHz
+oscillator, however most sound card manufacturer use slightly
+different oscillators as they are cheaper than 33MHz oscillators. If
+you have such a card you have to adjust the ad1816_clockfreq parameter
+above. For example: For a card using a 32.875MHz oscillator use
+ad1816_clockfreq=32875 instead of ad1816_clockfreq=33000.
+
+
+Updates, bugfixes and bugreports:
+--------------------------------
+
+As the driver is still experimental and under development, you should
+watch out for updates.  Updates of the driver are available on the
+internet from one of my home pages:
+  http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
+or:
+  http://www.tu-darmstadt.de/~tek01/projects/linux.html
+
+Bugreports, bugfixes and related questions should be sent via E-Mail to:
+  tek@rbg.informatik.tu-darmstadt.de
+
+
+Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
+          Last modified: 1998/11/06
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/ChangeLog.awe linux/Documentation/sound/ChangeLog.awe
--- v2.1.131/linux/Documentation/sound/ChangeLog.awe	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/ChangeLog.awe	Wed Dec 16 12:52:00 1998
@@ -0,0 +1,230 @@
+ver.0.4.3p4
+	- Bug fix for invalid memory detection when initialized twice
+	- Add sample sharing function - works together with awesfx-0.4.3p3
+	- Add AWE_PROBE_DATA for probing sample id
+
+ver.0.4.3p3
+	- Replace memset to MEMSET (for FreeBSD)
+	- Add PAN_EXCHANGE switch
+
+ver.0.4.3p2
+	- MIDI emulation device is added
+	- Controls volume and filter targets
+	- Include chorus/reverb/equalizer values in MISC_MODE
+
+ver.0.4.3p1
+	- Change the volume calculation method
+	- Support for Tom Lees' PnP driver (v0.3)
+
+ver.0.4.2d
+	- Support for OSS/Free 3.8 on 2.0 kernels.
+	- Support for Linux PnP driver
+	- Support for module (for recent 2.1 kernels and RH5.0)
+	- Support for FreeBSD-3.0 system
+
+ver.0.4.2c
+	- Add a mode to enable drum channel toggle via bank number
+	  change.
+
+ver.0.4.2b
+	- Clear voice position after note on
+	- Change nrvoices according to the current playing mode
+
+ver.0.4.2a
+	- Fix a bug in pitch calculation with scale parameter
+	- Change default chorus & reverb modes
+
+ver.0.4.2
+	- Use indirect voice allocation mode; used as default mode
+	- Add preset mapping
+	- Free buffers when resetting samples
+	- Set default preset/bank/drumset as variable
+	- Fix a bug in exclusive note-off
+	- Add channel reset control macro
+	- Change modwheel sensitivity as variable
+	- Add lock option in open_patch
+	- Add channel priority mode macro, and disable it as default
+	- Add unset effect macro
+	- Add user defined chorus/reverb modes
+	- Do not initialize effect parameters when allocating voices
+	- Accept realtime filter-Q parameter change
+	- Check value range of set/add effects
+	- Change drum flags automatically when receiving bank #128
+
+ver.0.4.1	development versions
+
+ver.0.4.0c
+	- Fix kernel oops when setting AWE_FX_ATTEN
+
+ver.0.4.0b
+	- Do not kill_note in start_note when velocity is zero
+
+ver.0.4.0a
+	- Fix a bug in channel pressure effects
+
+ver.0.4.0
+	- Support dynamic buffer allocation
+	- Add functions to open/close/unload a patch
+	- Change from pointer to integer index in voice/sample lists
+	- Support for Linux/Alpha-AXP
+	- Fix for FreeBSD
+	- Add sostenuto control
+	- Add midi channel priority
+	- Fix a bug in all notes off control
+	- Use AWE_DEFAULT_MEMSIZE always if defined
+	- Fix a bug in awe_reset causes seg fault when no DRAM onboard
+	- Use awe_mem_start variable instead of constant
+
+ver.0.3.3c
+	- Fix IOCTL_TO_USER for OSS-3.8 (on Linux-2.1.25)
+	- Fix i/o macros for mixer controls
+
+ver.0.3.3b
+	- Fix version number in awe_version.h
+	- Fix a small bug in noteoff/relese all
+
+ver.0.3.3a
+	- Fix all notes/sounds off
+	- Add layer effect control
+	- Add misc mode controls; realtime pan, version number, etc.
+	- Move gus bank control in misc mode control
+	- Modify awe_operations for OSS3.8b5
+	- Fix installation script
+
+ver.0.3.3
+	- Add bass/treble control in Emu8000 chip
+	- Add mixer device
+	- Fix sustain on to value 127
+
+ver.0.3.2
+	- Refuse linux-2.0.0 at installation
+	- Move awe_voice.h to /usr/include/linux
+
+ver.0.3.1b (not released)
+	- Rewrite chorus/reverb mode change functions
+	- Rewrite awe_detect & awe_check_dram routines
+
+ver.0.3.1a
+	- Fix a bug to reset voice counter in awe_reset
+	- Fix voice balance on GUS mode
+	- Make symlink on /usr/include/asm in install script
+
+ver.0.3.1
+	- Remove zero size arrays from awe_voice.h
+	- Fix init_fm routine
+	- Remove all samples except primary samples in REMOVE_LAST_SAMPLES
+
+ver.0.3.0a
+	- Add AWE_NOTEOFF_ALL control
+	- Remove AWE_INIT_ATTEN control
+
+ver.0.3.0
+	- Fix decay time table
+	- Add exclusive sounds mode
+	- Add capability to get current status
+
+ver.0.2.99e
+	- Add #ifdef for all sounds/notes off controls.
+	- Fix bugs on searching the default drumset/preset.
+	- Fix usslite patch to modify the default Config.in.
+
+ver.0.2.99d
+	- Fix bugs of attack/hold parameters
+	- Fix attack & decay time table
+
+ver.0.2.99c
+	- Change volume control messages (main & expression volume)
+	  to accesspt normal MIDI parameters in channel mode.
+	- Use channel mode in SEQ2 controls.
+
+ver.0.2.99b
+	- #ifdef patch manager functions (for OSS-3.7)
+
+ver.0.2.99a
+	- Fix sustain bug
+
+ver.0.2.99 (0.3 beta)
+	- Support multiple instruments
+
+ver.0.2.0c
+	- Add copyright notice
+	- FreeBSD 2.2-ALPHA integration
+
+ver.0.2.0b
+	- Remove buffered reading appended in v0.2.0a
+	- Remove SMAxW register check on writing
+	- Support Linux 2.1.x kernel
+	- Rewrite installation script
+
+ver.0.2.0a
+	- Define SEQUENCER_C for tuning.h for FreeBSD system
+	- Improvement of sample loading speed
+	- Fix installation script
+	- Add PnP driver functions for ISA PnP driver support
+
+ver.0.2.0
+	- Includes FreeBSD port
+	- Can load GUS compatible patches
+	- Change values of hardware control parameters for compatibility
+	  with GUS driver
+	- Accept 8bit or unsigned wave data
+	- Accept no blank loop data
+	- Add sample mode flags in sample_info
+
+ver.0.1.6
+	- Add voice effects control
+	- Fix awe_voice.h for word alignment
+
+ver.0.1.5c
+	- Fix FM(OPL) playback problem
+
+ver.0.1.5b
+	- Fix pitch calculation for fixed midi key
+
+ver.0.1.5a
+	- Fix bugs in removing samples from linked list.
+
+ver.0.1.5
+	- Add checksum verification for sample uploading
+	  (not compatible from older sample_info structure)
+	- Fix sample offset pointers to (actual value - 1)
+	- Add sequencer command to initialize awe32
+
+ver.0.1.4c
+	- Fix card detection and memory check function to avoid system crash
+	  at booting
+
+ver.0.1.4b
+	- Add release sustain mode
+	- Initialize FM each time after loading samples
+
+ver.0.1.4a
+	- Fix AWE card detection code
+	- Correct FM initialize position 
+	- Add non-releasing mode on voice info
+
+ver.0.1.4
+	- Add AWE card and DRAM detection codes
+	- Add FM initialization code
+	- Modify volume control
+	- Remove linear volume mode
+	- Change memory management; not using malloc dynamically
+	- Add remove-samples command
+	- Use internal id implicitly at loading samples
+
+ver.0.1.3
+	- Fix a bug on patch uploading to RAM
+
+ver.0.1.2
+	- Divide to separated packages
+	- Fix disagreed macro conditions
+	- Fix unresolved function bugs
+	- Integrate VoxWare and USS-Lite driver source (awe_voice.c)
+	  and remove awe_card.c
+
+ver.0.1.1
+	- Fix wrong sample numbers in sbktext
+	- Fix txt2sfx bug
+	- Fix pan parameter calculation
+	- Append USS-Lite/Linux2.0 driver
+
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/ChangeLog.multisound linux/Documentation/sound/ChangeLog.multisound
--- v2.1.131/linux/Documentation/sound/ChangeLog.multisound	Thu Sep 17 17:53:34 1998
+++ linux/Documentation/sound/ChangeLog.multisound	Wed Dec 16 12:52:00 1998
@@ -1,3 +1,16 @@
+1998-12-04  Andrew T. Veliath  <andrewtv@usa.net>
+
+	* Update version to 0.8.2.2
+
+	* Add msndreset program to shell archive.
+
+1998-11-11  Andrew T. Veliath  <andrewv@usa.net>
+
+	* msnd_pinnacle.c (mixer_ioctl): Add a mixer ioctl for
+	SOUND_MIXER_PRIVATE1 which does a full reset on the card.
+	(mixer_set): Move line in recording source to input monitor, aux
+	input level added, some mixer fixes.
+
 1998-09-10  Andrew Veliath  <andrewtv@usa.net>
 
 	* Update version to 0.8.2
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/ESS1868 linux/Documentation/sound/ESS1868
--- v2.1.131/linux/Documentation/sound/ESS1868	Thu Jul 16 18:09:22 1998
+++ linux/Documentation/sound/ESS1868	Wed Dec 16 12:52:00 1998
@@ -40,7 +40,7 @@
 
 # ESS1868F AudioDrive initialization
 
-/sbin/insmod sound
+/sbin/modprobe sound
 /sbin/insmod uart401
 /sbin/insmod sb io=0x220 irq=5 dma=1 dma16=-1
 /sbin/insmod mpu401 io=0x330
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/INSTALL.awe linux/Documentation/sound/INSTALL.awe
--- v2.1.131/linux/Documentation/sound/INSTALL.awe	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/INSTALL.awe	Wed Dec 16 12:52:00 1998
@@ -0,0 +1,137 @@
+================================================================
+	INSTALLATION OF AWE32 SOUND DRIVER FOR LINUX
+	Takashi Iwai	<iwai@ww.uni-erlangen.de>
+================================================================
+
+----------------------------------------------------------------
+* Attention to SB-PnP Card Users
+
+If you're using PnP cards, the initialization of PnP is required
+before loading this driver.  You have now three options:
+  1. Use isapnptools.
+  2. Install PnP kernel driver patch.
+  3. Initialize PnP on DOS/Windows, then boot linux by loadlin.
+In this document, only the case 1 case is treated.
+For the case 2, please refer to the instruction in PnP driver project.
+The home page of PnP driver project is the following URL:
+	http://www-jcr.lmh.ox.ac.uk/~pnp/
+
+----------------------------------------------------------------
+* Installation on RedHat 5.0 Sound Driver
+
+Please use install-rh.sh under RedHat5.0 directory.
+DO NOT USE install.sh below.
+See INSTALL.RH for more details.
+
+----------------------------------------------------------------
+* Installation/Update by Shell Script
+
+  1. Become root
+
+	% su
+
+  2. If you have never configured the kernel tree yet, run make config
+    once (to make depencies and symlinks).
+
+	# cd /usr/src/linux
+	# make xconfig
+    
+  3. Run install.sh script
+
+	# sh ./install.sh
+
+  4. Configure your kenrel
+
+	(for Linux 2.[01].x user)
+	# cd /usr/src/linux
+	# make xconfig (or make menuconfig)
+
+	(for Linux 1.2.x user)
+	# cd /usr/src/linux
+	# make config
+
+    Answer YES to both "lowlevel drivers" and "AWE32 wave synth" items 
+    in Sound menu.  ("lowlevel drivers" will appear only in 2.x
+    kernel.)
+
+  5. Make your kernel (and modules), and install them as usual.
+
+	5a. make kernel image
+		# make zImage
+
+	5b. make modules and install them
+		# make modules && make modules_install
+
+	5c. If you're using lilo, copy the kernel image and run lilo.
+	    Otherwise, copy the kernel image to suitable directory or
+	    media for your system.
+
+  6. Reboot the kernel if necessary.
+	- If you updated only the modules, you don't have to reboot
+	  the system.  Just remove the old sound modules here.
+		in 
+		# rmmod sound.o		(linux-2.0 or OSS/Free)
+		# rmmod awe_wave.o	(linux-2.1)
+
+  7. If your AWE card is a PnP and not initialized yet, you'll have to
+    do it by isapnp tools.  Otherwise, skip to 8.
+
+	This section described only a brief explanation.  For more
+	detaills, please see AWE64-Mini-HOWTO or isapnp tools FAQ.
+
+	7a. If you have no isapnp.conf file, generate it by pnpdump.
+	    Otherwise, skip to 7d.
+		# pnpdump > /etc/isapnp.conf
+
+	7b. Edit isapnp.conf file.  Comment out the appropriate
+	    lines containing desirable I/O ports, DMA and IRQs.
+	    Don't forget to enable (ACT Y) line.
+
+	7c. Add two i/o ports (0xA20 and 0xE20) in WaveTable part.
+	    ex)
+		(CONFIGURE CTL0048/58128 (LD 2
+		#     ANSI string -->WaveTable<--
+		  (IO 0 (BASE 0x0620))
+		  (IO 1 (BASE 0x0A20))
+		  (IO 2 (BASE 0x0E20))
+		  (ACT Y)
+		))
+
+	7d. Load the config file.
+	    CAUTION: This will reset all PnP cards!
+
+		# isapnp /etc/isapnp.conf
+
+  8. Load the sound module (if you configured it as a module):
+
+	for 2.0 kernel or OSS/Free monolithic module:
+
+		# modprobe sound.o
+
+	for 2.1 kernel:
+
+		# modprobe sound
+		# insmod uart401
+		# insmod sb io=0x220 irq=5 dma=1 dma16=5 mpu_io=0x330
+		(These values depend on your settings.)
+		# insmod awe_wave
+		(Be sure to load awe_wave after sb!)
+
+		See /usr/src/linux/Documentation/sound/AWE32 for
+		more details.
+
+  9. (only for obsolete systems) If you don't have /dev/sequencer
+     device file, make it according to Readme.linux file on
+     /usr/src/linux/drivers/sound. (Run a shell script included in
+     that file). <-- This file no longer exists in the recent kernels!
+
+  10. OK, load your own soundfont file, and enjoy MIDI!
+
+	% sfxload synthgm.sbk
+	% drvmidi foo.mid
+
+  11. For more advanced use (eg. dynamic loading, virtual bank and
+      etc.), please read the awedrv FAQ or the instructions in awesfx
+      and awemidi packages.
+
+Good luck!
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/Introduction linux/Documentation/sound/Introduction
--- v2.1.131/linux/Documentation/sound/Introduction	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/Introduction	Wed Dec 16 12:52:00 1998
@@ -0,0 +1,253 @@
+Soundcore	Notes on Modular Sound Drivers and Soundcore
+Wade Hampton 
+11/20/1998
+
+Purpose:  
+========
+This document provides some general notes on the modular 
+sound drivers and their configuration, along with the 
+support modules sound.o, soundlow.o and soundcore.o.
+
+Note, some of this probably should be added to the Sound-HOWTO!
+
+Copying:
+========
+none
+
+History:
+========
+0.1.0  11/20/1998  First version
+
+
+Modular Sound Drivers:
+======================
+
+Thanks to the GREAT work by Alan Cox (alan@lxorguk.ukuu.org.uk),
+
+[And Oleg Drokin, Thomas Sailer, Andrew Veliath and more than a few 
+ others - not to mention Hannu's original code being designed well
+ enough to cope with that kind of chopping up](Alan)
+
+the standard Linux kernels support a modular sound driver.  From
+Alan's comments in linux/drivers/sound/README.FIRST:
+
+  The modular sound driver patches were funded by Red Hat Software 
+  (www.redhat.com). The sound driver here is thus a modified version of 
+  Hannu's code. Please bear that in mind when considering the appropriate
+  forums for bug reporting.
+
+The modular sound drivers may be loaded via insmod or modprobe.  
+To support all the various sound modules, there are three general 
+support modules that must be loaded first:
+ 
+   soundcore.o:   Top level handler for the sound system, provides
+                  a set of functions for registration of devices
+                  by type.
+
+   soundlow.o:    Low-level sound drivers which are not part of 
+                  OSS/Lite (Open Sound System), including SB32/AWE
+                  synthesizer, etc.
+
+   sound.o:       Common sound functions required by all modules.
+
+For the specific sound modules (e.g., sb.o for the Soundblaster), 
+read the documentation on that module to determine what options
+are available, for example IRQ, address, DMA.
+
+Warning, the options for different cards sometime use different names 
+for the same or a similar feature (dma1= versus dma16=).  As a last 
+resort, inspect the code (search for MODULE_PARM).
+
+
+INSMOD:
+=======
+
+If loading via insmod, the common modules must be loaded in the 
+order below BEFORE loading the other sound modules.  The card-specific
+modules may then be loaded (most require parameters).  For example,
+I use the following via a shell script to load my SoundBlaster:
+
+SB_BASE=0x240
+SB_IRQ=9
+SB_DMA=3
+SB_DMA2=5
+SB_MPU=0x300
+#
+echo Starting sound
+/sbin/insmod soundcore
+/sbin/insmod soundlow
+/sbin/insmod sound  
+#
+echo Starting sound blaster....
+/sbin/insmod uart401
+/sbin/insmod sb io=$SB_BASE irq=$SB_IRQ dma=$SB_DMA dma16=$SB_DMA2 mpu_io=$SB_MP
+
+
+MODPROBE:
+=========
+
+If loading via modprobe, these common files are automatically loaded 
+when requested by modprobe.  For example, my /etc/conf.modules contains:
+
+alias sound sb 
+options sb io=0x240 irq=9 dma=3 dma16=5 mpu_io=0x300
+
+All you need to do to load the module is:
+
+	/sbin/modprobe sb
+
+
+Sound Status:
+=============
+
+The status of sound may be read/checked by:
+	cat /proc/sound
+	cat /dev/sndstat
+        cat (anyfile).au >/dev/audio
+
+The status of the modules and which modules depend on 
+which other modules may be checked by:
+	/sbin/lsmod
+
+/sbin/lsmod should show something like the following:
+	sb                     26280   0 
+	uart401                 5640   0  [sb]
+	sound                  57112   0  [sb uart401]
+	soundlow                 208   0  [sound]
+	soundcore               1968   8  [sb sound]
+
+
+Removing Sound:
+===============
+
+Sound may be removed by using /sbin/rmmod in the reverse order
+in which you load the modules.  Note, if a program has a sound device
+open (e.g., xmixer), that module (and the modules on which it 
+depends) may not be unloaded.
+
+For example, I use the following to remove my Soundblaster (rmmod
+in the reverse order in which I loaded the modules):
+
+/sbin/rmmod sb
+/sbin/rmmod uart401
+/sbin/rmmod sound
+/sbin/rmmod soundlow
+/sbin/rmmod soundcore
+
+
+Multiple Sound Cards:
+=====================
+
+The sound drivers will support multiple sound cards and there
+are some great applications like multitrack that support them.  
+Typically, you need two sound cards of different types.  Note, this
+uses more precious interrupts and DMA channels and sometimes 
+can be a configuration nightmare.  I have heard reports of 3-4
+sound cards (typically I only use 2).
+
+On my machine I have two sound cards (cs4232 and Soundblaster Vibra
+16).  By loading sound as modules, I can control which is the first
+sound device (/dev/dsp, /dev/audio, /dev/mixer) and which is 
+the second.  Normally, the cs4232 (Dell sound on the motherboard) 
+would be the first sound device, but I prefer the Soundblaster.  
+All you have to do is to load the one you want as /dev/dsp 
+first (in my case "sb") and then load the other one
+(in my case "cs4232").
+
+Warning:  I have never been able to get two PnP sound cards of the
+same type to load at the same time.  I have tried this several times
+with the Soundblaster Vibra 16 cards.  OSS has indicated that this
+is a PnP problem....  If anyone has any luck doing this, please 
+send me an E-MAIL.  PCI sound cards should not have this problem.
+
+
+Sound Problems:
+===============
+
+First RTFM (including the troubleshooting section 
+in the Sound-HOWTO). 
+
+1)  If you are having problems loading the modules (for
+    example, if you get device conflict errors) try the
+    following:
+
+  A)  If you have Win95 or NT on the same computer,  
+      write down what addresses, IRQ, and DMA channels
+      those were using for the same hardware.  You probably 
+      can use these addresses, IRQs, and DMA channels.
+  
+  B)  Check (cat) /proc/interrupts, /proc/ioports,
+      and /proc/dma.  Are you trying to use an address,
+      IRQ or DMA port that another device is using?
+  
+  C)  Check (cat) /proc/sys/pnp (if this exists, you 
+      may need a kernel patch to get this device).
+  
+  D)  Inspect your /var/log/messages file.  Often that will 
+      indicate what IRQ or IO port could not be obtained
+  
+  E)  Try another port or IRQ.  Note this may involve 
+      using the PnP tools to move the sound card to 
+      another location.
+
+2)  If you get motorboating (the same sound or part of a 
+    sound clip repeated), you probably have either an IRQ
+    or DMA conflict.  Move the card to another address.  This
+    has happened to me when playing long files when I had 
+    an IRQ conflict.
+
+3)  Ask for help on the sound list or send E-MAIL to the
+    sound driver author/maintainer.
+
+4)  Turn on debug in drivers/sound/sound_config.h (DEB, DDB, MDB).
+
+
+Configuring Sound:
+==================
+
+There are several ways of configuring your sound:
+
+1)  Hardcoded in the kernel at compile time (not applicable when
+    using sound modules).  This was the OLD way!
+
+2)  On the command line when using insmod.
+
+3)  In /etc/conf.modules when using modprobe.
+
+4)  Via RedHat's /usr/sbin/sndconfig program (text based).
+
+5)  Via the OSS soundconf program (with the commercial version
+    of the OSS driver.
+
+And I am sure, several other ways.  
+
+Anyone want to write a linuxconf module for configuring sound?
+
+
+
+For More Information (RTFM):
+============================
+1)  Information on kernel modules:  linux/Documentation/modules.txt
+    and manual pages for insmod and modprobe.
+
+2)  Information on PnP, RTFM manual pages for isapnp.
+
+3)  Sound-HOWTO and Sound-Playing-HOWTO.
+
+4)  OSS's WWW site at http://www.opensound.com.
+
+5)  All the files in linux/Documentation/sound.
+
+6)  The comments and code in linux/drivers/sound.
+
+7)  The sndconfig and rhsound documentation from RedHat.
+
+8)  The Linux-sound mailing list:  sound-list@redhat.com
+
+
+
+Contact Information:
+====================
+Wade Hampton:  (whampton@staffnet.com)
+
+
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/MultiSound linux/Documentation/sound/MultiSound
--- v2.1.131/linux/Documentation/sound/MultiSound	Fri Oct 23 22:01:19 1998
+++ linux/Documentation/sound/MultiSound	Wed Dec 16 12:52:00 1998
@@ -157,13 +157,13 @@
 #  
 #  * MultiSound Classic/Monterey/Tahiti:
 #  
-#  insmod soundcore
+#  modprobe soundcore
 #  insmod msnd
 #  insmod msnd_classic io=0x290 irq=7 mem=0xd0000
 #  
 #  * MultiSound Pinnacle in PnP mode:
 #  
-#  insmod soundcore
+#  modprobe soundcore
 #  insmod msnd
 #  isapnp mypinnacle.conf
 #  insmod msnd_pinnacle io=0x210 irq=5 mem=0xd8000 <-- match mypinnacle.conf values
@@ -359,8 +359,8 @@
 #  attempting to record at a sampling rate other than the DAT rate may
 #  be problematic (i.e. trying to record at 8000Hz when the DAT signal
 #  is 44100Hz).  If you have a problem with this, set the recording
-#  input to the line in if you need to record at a rate other than
-#  that of the DAT rate.
+#  input to analog if you need to record at a rate other than that of
+#  the DAT rate.
 #
 #
 #  -- Shell archive attached below, just run `sh MultiSound' to extract.
@@ -373,7 +373,7 @@
 # To extract the files from this archive, save it to some FILE, remove
 # everything before the `!/bin/sh' line above, then type `sh FILE'.
 #
-# Made on 1998-09-05 08:26 EDT by <andrewtv@ztransform.velsoft.com>.
+# Made on 1998-12-04 10:07 EST by <andrewtv@ztransform.velsoft.com>.
 # Source directory was `/home/andrewtv/programming/pinnacle/pinnacle'.
 #
 # Existing files will *not* be overwritten unless `-c' is specified.
@@ -381,10 +381,11 @@
 # This shar contains:
 # length mode       name
 # ------ ---------- ------------------------------------------
-#   2111 -rw-rw-r-- MultiSound.d/setdigital.c
-#  10301 -rw-rw-r-- MultiSound.d/pinnaclecfg.c
-#     96 -rw-rw-r-- MultiSound.d/Makefile
+#   2046 -rw-rw-r-- MultiSound.d/setdigital.c
+#  10235 -rw-rw-r-- MultiSound.d/pinnaclecfg.c
+#    106 -rw-rw-r-- MultiSound.d/Makefile
 #    141 -rw-rw-r-- MultiSound.d/conv.l
+#   1472 -rw-rw-r-- MultiSound.d/msndreset.c
 #
 save_IFS="${IFS}"
 IFS="${IFS}:"
@@ -431,7 +432,7 @@
 fi
 rm -f 1231235999 $$.touch
 #
-if mkdir _sh21233; then
+if mkdir _sh01426; then
   $echo 'x -' 'creating lock directory'
 else
   $echo 'failed to create lock directory'
@@ -467,8 +468,6 @@
 X * along with this program; if not, write to the Free Software
 X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 X *
-X * $Id: setdigital.c,v 1.1 1998/08/29 03:32:33 andrewtv Exp $
-X *
 X ********************************************************************/
 X
 #include <stdio.h>
@@ -528,19 +527,19 @@
 X	return 0;
 }
 SHAR_EOF
-  $shar_touch -am 0828233298 'MultiSound.d/setdigital.c' &&
+  $shar_touch -am 1204092598 'MultiSound.d/setdigital.c' &&
   chmod 0664 'MultiSound.d/setdigital.c' ||
   $echo 'restore of' 'MultiSound.d/setdigital.c' 'failed'
   if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
   && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
     md5sum -c << SHAR_EOF >/dev/null 2>&1 \
     || $echo 'MultiSound.d/setdigital.c:' 'MD5 check failed'
-47720746d4367bae9954787c311c56fd  MultiSound.d/setdigital.c
+e87217fc3e71288102ba41fd81f71ec4  MultiSound.d/setdigital.c
 SHAR_EOF
   else
     shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/setdigital.c'`"
-    test 2111 -eq "$shar_count" ||
-    $echo 'MultiSound.d/setdigital.c:' 'original size' '2111,' 'current size' "$shar_count!"
+    test 2046 -eq "$shar_count" ||
+    $echo 'MultiSound.d/setdigital.c:' 'original size' '2046,' 'current size' "$shar_count!"
   fi
 fi
 # ============= MultiSound.d/pinnaclecfg.c ==============
@@ -575,8 +574,6 @@
 X * along with this program; if not, write to the Free Software
 X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 X *
-X * $Id: pinnaclecfg.c,v 1.3 1998/08/29 03:32:32 andrewtv Exp $
-X *
 X ********************************************************************/
 X
 #include <stdio.h>
@@ -984,19 +981,19 @@
 X	return 0;
 }
 SHAR_EOF
-  $shar_touch -am 0905082598 'MultiSound.d/pinnaclecfg.c' &&
+  $shar_touch -am 1204092598 'MultiSound.d/pinnaclecfg.c' &&
   chmod 0664 'MultiSound.d/pinnaclecfg.c' ||
   $echo 'restore of' 'MultiSound.d/pinnaclecfg.c' 'failed'
   if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
   && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
     md5sum -c << SHAR_EOF >/dev/null 2>&1 \
     || $echo 'MultiSound.d/pinnaclecfg.c:' 'MD5 check failed'
-71f99b834a2845daae8ae034623e313e  MultiSound.d/pinnaclecfg.c
+366bdf27f0db767a3c7921d0a6db20fe  MultiSound.d/pinnaclecfg.c
 SHAR_EOF
   else
     shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/pinnaclecfg.c'`"
-    test 10301 -eq "$shar_count" ||
-    $echo 'MultiSound.d/pinnaclecfg.c:' 'original size' '10301,' 'current size' "$shar_count!"
+    test 10235 -eq "$shar_count" ||
+    $echo 'MultiSound.d/pinnaclecfg.c:' 'original size' '10235,' 'current size' "$shar_count!"
   fi
 fi
 # ============= MultiSound.d/Makefile ==============
@@ -1007,26 +1004,26 @@
   sed 's/^X//' << 'SHAR_EOF' > 'MultiSound.d/Makefile' &&
 CC	= gcc
 CFLAGS	= -O
-PROGS	= setdigital pinnaclecfg conv
+PROGS	= setdigital msndreset pinnaclecfg conv
 X
 all: $(PROGS)
 X
 clean:
 X	rm -f $(PROGS)
 SHAR_EOF
-  $shar_touch -am 0828231798 'MultiSound.d/Makefile' &&
+  $shar_touch -am 1204092398 'MultiSound.d/Makefile' &&
   chmod 0664 'MultiSound.d/Makefile' ||
   $echo 'restore of' 'MultiSound.d/Makefile' 'failed'
   if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
   && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
     md5sum -c << SHAR_EOF >/dev/null 2>&1 \
     || $echo 'MultiSound.d/Makefile:' 'MD5 check failed'
-ab95a049d10611a5e5d559a56965b33f  MultiSound.d/Makefile
+76ca8bb44e3882edcf79c97df6c81845  MultiSound.d/Makefile
 SHAR_EOF
   else
     shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/Makefile'`"
-    test 96 -eq "$shar_count" ||
-    $echo 'MultiSound.d/Makefile:' 'original size' '96,' 'current size' "$shar_count!"
+    test 106 -eq "$shar_count" ||
+    $echo 'MultiSound.d/Makefile:' 'original size' '106,' 'current size' "$shar_count!"
   fi
 fi
 # ============= MultiSound.d/conv.l ==============
@@ -1059,5 +1056,82 @@
     $echo 'MultiSound.d/conv.l:' 'original size' '141,' 'current size' "$shar_count!"
   fi
 fi
-rm -fr _sh21233
+# ============= MultiSound.d/msndreset.c ==============
+if test -f 'MultiSound.d/msndreset.c' && test "$first_param" != -c; then
+  $echo 'x -' SKIPPING 'MultiSound.d/msndreset.c' '(file already exists)'
+else
+  $echo 'x -' extracting 'MultiSound.d/msndreset.c' '(text)'
+  sed 's/^X//' << 'SHAR_EOF' > 'MultiSound.d/msndreset.c' &&
+/*********************************************************************
+X *
+X * msndreset.c - resets the MultiSound card
+X *
+X * Copyright (C) 1998 Andrew Veliath
+X *
+X * This program is free software; you can redistribute it and/or modify
+X * it under the terms of the GNU General Public License as published by
+X * the Free Software Foundation; either version 2 of the License, or
+X * (at your option) any later version.
+X *
+X * This program is distributed in the hope that it will be useful,
+X * but WITHOUT ANY WARRANTY; without even the implied warranty of
+X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+X * GNU General Public License for more details.
+X *
+X * You should have received a copy of the GNU General Public License
+X * along with this program; if not, write to the Free Software
+X * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+X *
+X ********************************************************************/
+X
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+X
+int main(int argc, char *argv[])
+{
+X	int fd;
+X
+X	if (argc != 2) {
+X		fprintf(stderr, "usage: msndreset <mixer device>\n");
+X		exit(1);
+X	}
+X
+X	if ((fd = open(argv[1], O_RDWR)) < 0) {
+X		perror(argv[1]);
+X		exit(1);
+X	}
+X
+X	if (ioctl(fd, SOUND_MIXER_PRIVATE1, 0) < 0) {
+X		fprintf(stderr, "error: msnd ioctl reset failed\n");
+X		perror("ioctl");
+X		close(fd);
+X		exit(1);
+X	}
+X
+X	close(fd);
+X	
+X	return 0;
+}
+SHAR_EOF
+  $shar_touch -am 1204100698 'MultiSound.d/msndreset.c' &&
+  chmod 0664 'MultiSound.d/msndreset.c' ||
+  $echo 'restore of' 'MultiSound.d/msndreset.c' 'failed'
+  if ( md5sum --help 2>&1 | grep 'sage: md5sum \[' ) >/dev/null 2>&1 \
+  && ( md5sum --version 2>&1 | grep -v 'textutils 1.12' ) >/dev/null; then
+    md5sum -c << SHAR_EOF >/dev/null 2>&1 \
+    || $echo 'MultiSound.d/msndreset.c:' 'MD5 check failed'
+c52f876521084e8eb25e12e01dcccb8a  MultiSound.d/msndreset.c
+SHAR_EOF
+  else
+    shar_count="`LC_ALL= LC_CTYPE= LANG= wc -c < 'MultiSound.d/msndreset.c'`"
+    test 1472 -eq "$shar_count" ||
+    $echo 'MultiSound.d/msndreset.c:' 'original size' '1472,' 'current size' "$shar_count!"
+  fi
+fi
+rm -fr _sh01426
 exit 0
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/OPL3-SA2 linux/Documentation/sound/OPL3-SA2
--- v2.1.131/linux/Documentation/sound/OPL3-SA2	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/OPL3-SA2	Fri Dec 18 09:33:39 1998
@@ -0,0 +1,121 @@
+Documentation for the OPL3-SA2, SA3, and SAx driver (opl3sa2.o)
+---------------------------------------------------------------
+
+Scott Murray, scottm@interlog.com
+December, 1998
+
+NOTE: All trademarked terms mentioned below are properties of their
+      respective owners.
+
+This driver is for PnP soundcards based on the following Yamaha audio
+controller chipsets:
+
+YMF711 aka OPL3-SA2
+YMF715 aka OPL3-SA3
+YMF719 aka OPL3-SAx (?)
+
+I'm a little fuzzy on what is classified a SAx, as I've seen the label
+used to refer to the whole 7xx family and as a specific identifier for
+the 719 on my no-name soundcard.  To make matters worse, there seem to
+be several reversions of the 715 chipset.
+
+Anyways, all of these chipsets implement the following devices:
+
+OPL3 FM synthesizer
+Soundblaster Pro
+Microsoft/Windows Sound System
+MPU401 MIDI interface
+
+Note that this driver uses the MSS device, and to my knowledge these
+chipsets enforce an either/or situation with the Soundblaster Pro
+device and the MSS device.  Since the MSS device has better
+capabilities, I have implemented the driver to use it.
+
+Being PnP cards, some configuration is required.  There are two ways
+of doing this.  The most common is to use the isapnptools package to
+initialize the card, and use the kernel module form of the sound
+subsystem and sound drivers.  Alternatively, some BIOS's allow manual
+configuration of installed PnP devices in the BIOS menus, which should
+allow using the non-modular sound drivers, i.e. built into the kernel.
+
+I personally use isapnp and modules, and do not have access to a PnP
+BIOS machine to test.  If you have such a beast, try building both the
+MSS driver and this driver into the kernel (appropiately configured,
+of course) and let me know if it works.  If it does not, then email me
+if you are willing to experiment in an effort to make it work.
+
+If you are using isapnp, follow the directions in its documentation to
+produce a configuration file.  Here is the relevant excerpt for my SAx
+card from my isapnp.conf:
+
+(CONFIGURE YMH0800/-1 (LD 0
+
+# Instead of (IO 0 (BASE 0x0220)), disable SB:
+(IO 0 (BASE 0x0000))
+(IO 1 (BASE 0x0530))
+(IO 2 (BASE 0x0388))
+(IO 3 (BASE 0x0330))
+(IO 4 (BASE 0x0370))
+(INT 0 (IRQ 7 (MODE +E)))
+(DMA 0 (CHANNEL 0))
+(DMA 1 (CHANNEL 3))
+
+Here, note that:
+
+Port  Acceptable Range  Purpose
+----  ----------------  -------
+IO 0  0x0220 - 0x0280   SB base address, I set to 0 just to be safe.
+IO 1  0x0530 - 0x0F48   MSS base address
+IO 2  0x0388 - 0x03F8   OPL3 base address
+IO 3  0x0300 - 0x0334   MPU base address
+IO 4  0x0100 - 0x0FFE   card's own base address for its control I/O ports
+
+The IRQ and DMA values can be any that considered acceptable for a
+MSS.  Assuming you've got isapnp all happy, then you should be able to
+do something like the following (which matches up with the isapnp
+configuration above):
+
+insmod mpu401
+insmod ad1848
+insmod opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
+insmod opl3 io=0x388
+
+Remeber that the opl3sa2 module's io argument is for it's own control
+port, which handles the card's master mixer for volume (on all cards),
+and bass and treble (on SA3 and SAx).
+
+If all goes well an you see no error messages, you should be able to
+start using the sound capabilities of your system.  If you get an
+error message while trying to insert the opl3sa2 module, then make
+sure that the values of the various arguments match what you specified
+in your isapnp configuration file, and that there is no conflict with
+another device for an I/O port or interrupt.  Checking the contents of
+/proc/ioports and /proc/interrupts can be useful to see if you're
+butting heads with another device.
+
+If you still cannot get the module to load, look at the contents of
+your system log file, usually /var/log/messages.  If you see the
+message "No Yamaha audio controller found", then you have a different
+chipset than I've encountered so far.  Look for a line in the log file
+that says "opl3sa2.c: chipset version = <some number>".  If you want
+me to add support for your card, send me the number from this line and
+any information you have on the make and chipset of your sound card,
+and I may be able to work up something.  If you do not see these
+messages, and any of the other messages present in the log are not
+helpful, email me some details and I'll try my best to help.
+
+To set up automatic module loading with kmod, the kernel module loader,
+I currently use the following section in my conf.modules file:
+
+# Sound
+alias char-major-14 opl3sa2
+pre-install opl3sa2 modprobe "-k" "ad1848"
+post-install opl3sa2 modprobe "-k" "opl3"
+options opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
+options opl3 io=0x388
+
+That's all it currently takes to get an OPL3-SAx card working on my
+system.  Once again, if you have any other problems, email me at the
+address listed above.
+
+Scott
diff -u --recursive --new-file v2.1.131/linux/Documentation/sound/README.awe linux/Documentation/sound/README.awe
--- v2.1.131/linux/Documentation/sound/README.awe	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/README.awe	Wed Dec 16 12:52:00 1998
@@ -0,0 +1,219 @@
+================================================================
+	AWE32 Sound Driver for Linux / FreeBSD
+		version 0.4.3; Nov. 1, 1998
+
+	Takashi Iwai <iwai@ww.uni-erlangen.de>
+================================================================
+
+* GENERAL NOTES
+
+This is a sound driver extension for SoundBlaster AWE32 and other
+compatible cards (AWE32-PnP, SB32, SB32-PnP, AWE64 & etc) to enable
+the wave synth operations.  The driver is provided for both Linux
+1.2.x and 2.[01].x kernels, and also FreeBSD, on Intel x86 and DEC
+Alpha systems.
+
+This driver was written by Takashi Iwai <iwai@ww.uni-erlangen.de>,
+and provided "as is".  The original source (awedrv-0.4.3.tar.gz) and
+binary packages are available on the following URL:
+	http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
+Note that since the author is apart from this web site, the update is
+not frequent now.
+
+
+* NOTE TO LINUX USERS
+
+To enable this driver on linux-2.[01].x kernels, you need turn on both 
+"lowlevel drivers support" and "AWE32 synth support" options in sound
+menu when configure your linux kernel and modules.  The precise
+installation procedure is described in the AWE64-Mini-HOWTO and
+linux-kernel/Documetation/sound/AWE32.
+
+If you're using PnP cards, the card must be initialized before loading
+the sound driver.  There're several options to do this:
+    - Initialize the card via ISA PnP tools, and load the sound module.
+    - Initialize the card on DOS, and load linux by loadlin.exe
+    - Use PnP kernel driver (for Linux-2.x.x)
+The detailed instruction for the solution using isapnp tools is found
+in many documents like above.  A brief instruction is also included in
+the installation document of this package.
+For PnP driver project, please refer to the following URL:
+	http://www-jcr.lmh.ox.ac.uk/~pnp/
+
+
+* USING THE DRIVER
+
+The awedrv has several different playing modes to realize easy channel 
+allocation for MIDI songs.  To hear the exact sound quality, you need
+to obtain the extended sequencer program, drvmidi or playmidi-2.5.
+
+For playing MIDI files, you *MUST* load the soundfont file on the
+driver previously by sfxload utility.  Otherwise you'll here no sounds 
+at all!  All the utilities and driver source packages are found in the
+above URL.  The sfxload program is included in the package
+awesfx-0.4.3.tgz.  Binary packages are available there, too.  See the
+instruction in each package for installation.
+
+Loading a soundfont file is very simple.  Just execute the command
+
+	% sfxload synthgm.sbk
+
+Then, sfxload transfers the file "synthgm.sbk" to the driver.
+Both SF1 and SF2 formats are accepted.
+
+Now you can hear midi musics by a midi player.
+
+	% drvmidi foo.mid
+
+If you run MIDI player after MOD player, you need to load soundfont
+files again, since MOD player programs clear the previous loaded
+samples by their own data.
+
+If you have only 512kb on the sound card, I recommend to use dynamic
+sample loading via -L option of drvmidi.  2MB GM/GS soundfont file is
+available in most midi files.
+
+	% sfxload synthgm
+	% drvmidi -L 2mbgmgs foo.mid
+
+This makes a big differece (believe me)!  For more details, please
+refer to the FAQ list which is available on the URL above.
+
+The current chorus, reverb and equalizer status can be changed by
+aweset utility program (included in awesfx package).  Note that
+some awedrv-native programs (like drvmidi and xmp) will change the
+current settings by themselves.  The aweset program is effective
+only for other programs like playmidi.
+
+Enjoy.
+
+
+* COMPILE FLAGS
+
+Compile conditions are defined in awe_config.h.
+
+[Compatibility Conditions]
+The following flags are defined automatically when using installation
+shell script.
+
+- AWE_MODULE_SUPPORT
+    indicates your linux kernel supports module for each soundcard
+    (in recent 2.1 kernels and unofficial patched 2.0 kernels as
+     distributed in the RH5.0 package).
+    This flag is automatically set when you're using 2.1.x kernels.
+    You can pass the base address and memory size via the following
+    module options,
+	io = base I/O port address (eg. 0x620)
+	memsize = DRAM size in Kbyes (eg. 512)
+    As default, AWE driver probes these values automatically.
+
+
+[Hardware Conditions]
+You DON'T have to define the following two values.
+Define them only when the driver couldn't detect the card properly.
+
+- AWE_DEFAULT_BASE_ADDR		(default: not defined)
+    specifies the base port address of your AWE32 card.
+    0 means to autodetect the address.
+
+- AWE_DEFAULT_MEM_SIZE		(default: not defined)
+    specifies the memory size of your AWE32 card in kilo bytes.
+    -1 means to autodetect its size.
+    
+
+[Sample Table Size]
+From ver.0.4.0, sample tables are allocated dynamically (except
+Linux-1.2.x system), so you need NOT to touch these parameters.
+Linux-1.2.x users may need to increase these values to apropriate size 
+if larger DRAM is equipped with the soundcard.
+
+- AWE_MAX_SF_LISTS, AWE_MAX_SAMPLES, AWE_MAX_INFOS
+
+
+[Other Conditions]
+
+- AWE_ALWAYS_INIT_FM		(default: not defined)
+    indicates the AWE driver always initialize FM passthrough even
+    without DRAM on board.  Emu8000 chip has a restriction for playing
+    samples on DRAM that at least two channels must be occupied as
+    passthrough channels. 
+
+- AWE_DEBUG_ON			(default: defined)
+    turns on debuggin messages if defined.
+
+- AWE_HAS_GUS_COMPATIBILITY	(default: defined)
+    Enables GUS compatibility mode if defined, reading GUS patches and 
+    GUS control commands.  Define this option to use GMOD or other
+    GUS module players.
+
+- CONFIG_AWE32_MIDIEMU		(default: defined)
+    Adds a MIDI emulation device by Emu8000 wavetable.  The emulation
+    device can be accessed as an external MIDI, and sends the MIDI
+    control codes directly.  XG and GS sysex/NRPN are accepted.
+    No MIDI input is supported.
+
+- CONFIG_AWE32_MIXER		(default: not defined)
+    Adds a mixer device for AWE32 bass/treble equalizer control.
+    You can access this device using /dev/mixer?? (usually mixer01).
+
+- AWE_USE_NEW_VOLUME_CALC	(default: defined)
+    Use the new method to calculate the volume change as compatible
+    with DOS/Win drivers.  This option can be toggled via aweset
+    program, or drvmidi player.
+
+- AWE_CHECK_VTARGET		(default: defined)
+    Check the current volume target value when searching for an
+    empty channel to allocate a new voice.  This is experimentally
+    implemented in this version.  (probably, this option doesn't
+    affect the sound quality severely...)
+
+- AWE_ALLOW_SAMPLE_SHARING	(default: defined)
+   Allow sample sharing for differently loaded patches.
+   This function is available only together with awesfx-0.4.3p3.
+   Note that this is still an experimantal option.
+
+- DEF_FM_CHORUS_DEPTH		(default: 0x10)
+    The default strength to be sent to the chorus effect engine.
+    From 0 to 0xff.  Larger numbers may often cause weird sounds.
+
+- DEF_FM_REVERB_DEPTH		(default: 0x10)
+    The default strength to be sent to the reverb effect engine.
+    From 0 to 0xff.  Larger numbers may often cause weird sounds.
+
+
+* ACKNOWLEDGMENTS
+
+Thanks to Witold Jachimczyk (witek@xfactor.wpi.edu) for many advices
+to programming of AWE32.  Many codes are brought from his AWE32-native 
+MOD player, ALMP.
+The port of awedrv to FreeBSD is done by Randall Hopper
+(rhh@ct.picker.com).
+The new volume calculation routine was derived from Mark Weaver's
+ADIP compatible routines.
+I also thank linux-awe-ml members for their efforts
+to reboot their system many times :-)
+
+
+* TODO'S
+
+- Complete DOS/Win compatibility
+- DSP-like output
+
+
+* COPYRIGHT
+
+Copyright (C) 1996-1998 Takashi Iwai
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
diff -u --recursive --new-file v2.1.131/linux/Documentation/video4linux/bttv/CARDS linux/Documentation/video4linux/bttv/CARDS
--- v2.1.131/linux/Documentation/video4linux/bttv/CARDS	Wed Aug 26 11:37:33 1998
+++ linux/Documentation/video4linux/bttv/CARDS	Wed Dec 16 12:53:13 1998
@@ -90,15 +90,14 @@
 
 AverMedia
 ---------
-
 ...
 
 
+ADS Channel Surfer
+------------------
+...
 
 
-
- 
-
-
-
-
+Maxi TV Video PCI 2 card
+------------------------
+...
diff -u --recursive --new-file v2.1.131/linux/Makefile linux/Makefile
--- v2.1.131/linux/Makefile	Wed Dec 16 10:32:54 1998
+++ linux/Makefile	Fri Dec 18 14:01:48 1998
@@ -1,18 +1,9 @@
 VERSION = 2
 PATCHLEVEL = 1
-SUBLEVEL = 131
+SUBLEVEL = 132
 
 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
 
-#
-# For SMP kernels, set this. We don't want to have this in the config file
-# because it makes re-config very ugly and too many fundamental files depend
-# on "CONFIG_SMP"
-#
-# For UP operations COMMENT THIS OUT, simply setting SMP = 0 won't work
-#
-SMP = 1
-
 .EXPORT_ALL_VARIABLES:
 
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
@@ -94,7 +85,7 @@
 
 CFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer
 
-ifdef SMP
+ifdef CONFIG_SMP
 CFLAGS += -D__SMP__
 AFLAGS += -D__SMP__
 endif
@@ -180,6 +171,18 @@
 DRIVERS := $(DRIVERS) drivers/net/hamradio/hamradio.a
 endif
 
+ifeq ($(CONFIG_USB),y)
+DRIVERS := $(DRIVERS) drivers/uusbd/usb.a
+endif
+
+ifeq ($(CONFIG_I2O),y)
+DRIVERS := $(DRIVERS) drivers/i2o/i2o.a
+endif
+
+ifeq ($(CONFIG_IRDA),y)
+DRIVERS := $(DRIVERS) drivers/net/irda/irda_drivers.a
+endif
+
 include arch/$(ARCH)/Makefile
 
 .S.s:
@@ -195,11 +198,13 @@
 
 vmlinux: $(CONFIGURATION) init/main.o init/version.o linuxsubdirs
 	$(LD) $(LINKFLAGS) $(HEAD) init/main.o init/version.o \
+		--start-group \
 		$(CORE_FILES) \
 		$(FILESYSTEMS) \
 		$(NETWORKS) \
 		$(DRIVERS) \
 		$(LIBS) \
+		--end-group \
 		-o vmlinux
 	$(NM) vmlinux | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)' | sort > System.map
 
@@ -256,7 +261,7 @@
 
 include/linux/compile.h: $(CONFIGURATION) include/linux/version.h newversion
 	@echo -n \#define UTS_VERSION \"\#`cat .version` > .ver
-	@if [ -n "$(SMP)" ] ; then echo -n " SMP" >> .ver; fi
+	@if [ -n "$(CONFIG_SMP)" ] ; then echo -n " SMP" >> .ver; fi
 	@if [ -f .name ]; then  echo -n \-`cat .name` >> .ver; fi
 	@echo ' '`date`'"' >> .ver
 	@echo \#define LINUX_COMPILE_TIME \"`date +%T`\" >> .ver
@@ -307,6 +312,7 @@
 		mkdir -p $$MODLIB/$$2; cp $$These $$MODLIB/$$2; \
 		echo Installing modules under $$MODLIB/$$2; \
 	}; \
+	mkdir -p $$MODLIB; \
 	\
 	if [ -f BLOCK_MODULES ]; then inst_mod BLOCK_MODULES block; fi; \
 	if [ -f NET_MODULES   ]; then inst_mod NET_MODULES   net;   fi; \
@@ -320,6 +326,7 @@
 	if [ -f SOUND_MODULES ]; then inst_mod SOUND_MODULES sound; fi; \
 	if [ -f VIDEO_MODULES ]; then inst_mod VIDEO_MODULES video; fi; \
 	if [ -f FC4_MODULES   ]; then inst_mod FC4_MODULES   fc4;   fi; \
+	if [ -f IRDA_MODULES  ]; then inst_mod IRDA_MODULES  net;   fi; \
 	\
 	ls *.o > $$MODLIB/.allmods; \
 	echo $$MODULES | tr ' ' '\n' | sort | comm -23 $$MODLIB/.allmods - > $$MODLIB/.misc; \
@@ -404,6 +411,9 @@
 
 checkconfig:
 	perl -w scripts/checkconfig.pl `find * -name '*.[hcS]' -print | sort`
+
+checkhelp:
+	perl -w scripts/checkhelp.pl `find * -name [cC]onfig.in -print`
 
 ifdef CONFIGURATION
 ..$(CONFIGURATION):
diff -u --recursive --new-file v2.1.131/linux/Rules.make linux/Rules.make
--- v2.1.131/linux/Rules.make	Tue Aug 18 22:02:01 1998
+++ linux/Rules.make	Fri Dec 18 14:01:48 1998
@@ -197,7 +197,7 @@
 # and SMP Intel boxes - AC - from bits by Michael Chastain
 #
 
-ifdef SMP
+ifdef CONFIG_SMP
 	genksyms_smp_prefix := -p smp_
 else
 	genksyms_smp_prefix := 
diff -u --recursive --new-file v2.1.131/linux/arch/alpha/config.in linux/arch/alpha/config.in
--- v2.1.131/linux/arch/alpha/config.in	Wed Dec 16 10:32:54 1998
+++ linux/arch/alpha/config.in	Fri Dec 18 14:01:48 1998
@@ -167,6 +167,8 @@
 	define_bool CONFIG_ALPHA_AVANTI y
 fi
 
+bool 'Symmetric multi-processing support' CONFIG_SMP
+
 if [ "$CONFIG_PCI" = "y" ]; then
   bool 'PCI quirks' CONFIG_PCI_QUIRKS
   if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
diff -u --recursive --new-file v2.1.131/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.1.131/linux/arch/alpha/kernel/Makefile	Wed Sep  9 14:51:03 1998
+++ linux/arch/alpha/kernel/Makefile	Fri Dec 18 14:01:48 1998
@@ -111,7 +111,7 @@
 
 endif # GENERIC
 
-ifdef SMP
+ifdef CONFIG_SMP
 O_OBJS   += smp.o
 endif
 
diff -u --recursive --new-file v2.1.131/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.1.131/linux/arch/alpha/kernel/alpha_ksyms.c	Fri Nov 27 13:09:21 1998
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Fri Dec 18 09:33:39 1998
@@ -52,6 +52,7 @@
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
 EXPORT_SYMBOL(screen_info);
+EXPORT_SYMBOL(perf_irq);
 
 /* platform dependent support */
 EXPORT_SYMBOL(_inb);
diff -u --recursive --new-file v2.1.131/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.1.131/linux/arch/alpha/kernel/irq.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/alpha/kernel/irq.c	Fri Dec 18 09:33:39 1998
@@ -84,6 +84,15 @@
 	}
 }
 
+
+
+static void dummy_perf(unsigned long vector, struct pt_regs *regs)
+{
+        printk(KERN_CRIT "Performance counter interrupt!\n");
+}
+
+void (*perf_irq)(unsigned long, struct pt_regs *) = dummy_perf;
+
 /*
  * Dispatch device interrupts.
  */
@@ -879,8 +888,8 @@
 		__restore_flags(flags);
 		return;
 	case 4:
-		printk("Performance counter interrupt\n");
-		break;
+		perf_irq(vector, &regs);
+		return;
 	default:
 		printk("Hardware intr %ld %lx? Huh?\n", type, vector);
 	}
diff -u --recursive --new-file v2.1.131/linux/arch/alpha/kernel/sys_sio.c linux/arch/alpha/kernel/sys_sio.c
--- v2.1.131/linux/arch/alpha/kernel/sys_sio.c	Sun Nov  8 14:02:41 1998
+++ linux/arch/alpha/kernel/sys_sio.c	Fri Dec 18 09:33:39 1998
@@ -232,7 +232,7 @@
 	 * selected... :-(
 	 */
 	layout_all_busses(DEFAULT_IO_BASE, APECS_AND_LCA_DEFAULT_MEM_BASE);
-	sio_pci_fixup(noname_map_irq, 0x0b0a0f09);
+	sio_pci_fixup(noname_map_irq, 0x0b0a0f0e);
 	sio_fixup_irq_levels(sio_collect_irq_levels());
         enable_ide(0x26e);
 }
diff -u --recursive --new-file v2.1.131/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.1.131/linux/arch/arm/Makefile	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/Makefile	Thu Dec 17 09:05:42 1998
@@ -120,6 +120,7 @@
 endif
 
 ifeq ($(CONFIG_ARCH_VNC),y)
+TEXTADDR	 = 0xC000C000
 MACHINE		 = vnc
 ARCHDIR		 = vnc
 endif
@@ -141,7 +142,7 @@
 OBJDUMP		 = $(CROSS_COMPILE)objdump
 CPP		 = $(CC) -E
 ARCHCC		:= $(word 1,$(CC))
-GCCLIB		:= `$(ARCHCC) $(CFLAGS_PROC) --print-libgcc-file-name`
+GCCLIB		:= `$(CC) $(CFLAGS_PROC) --print-libgcc-file-name`
 #GCCARCH		:= -B/usr/bin/arm-linuxelf- 
 HOSTCFLAGS	:= $(CFLAGS:-fomit-frame-pointer=)
 ifeq ($(CONFIG_FRAME_POINTER),y)
@@ -160,10 +161,10 @@
 BLOCK_DRIVERS	:= drivers/block/block.a
 CDROM_DRIVERS	:= drivers/cdrom/cdrom.a
 ifeq ($(CONFIG_FB),y)
-CHAR_DRIVERS	:= arch/arm/drivers/char1/char.a
+CHAR_DRIVERS	:= arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a
 else
 ifeq ($(CONFIG_VGA_CONSOLE),y)
-CHAR_DRIVERS	:= arch/arm/drivers/char1/char.a
+CHAR_DRIVERS	:= arch/arm/drivers/char1/char1.a drivers/char/char.a arch/arm/drivers/char1/char1.a
 else
 CHAR_DRIVERS	:= arch/arm/drivers/char/char.a
 endif
diff -u --recursive --new-file v2.1.131/linux/arch/arm/config.in linux/arch/arm/config.in
--- v2.1.131/linux/arch/arm/config.in	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/config.in	Thu Dec 17 09:05:42 1998
@@ -38,15 +38,22 @@
   define_bool CONFIG_BUS_I2C y
 fi
 
-#  These machines have PCI/may have PCI
+#  These machines always have PCI
 
 if [ "$CONFIG_ARCH_NEXUSPCI" = "y" -o \
      "$CONFIG_ARCH_VNC" = "y" ]; then
   define_bool CONFIG_PCI y
+fi
+if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
+  bool "PCI support" CONFIG_PCI
+fi
+
+# These machines have ISA-DMA
+if [ "$CONFIG_CATS" = "y" -o \
+     "$CONFIG_ARCH_VNC" = "y" ]; then
+  define_bool CONFIG_ISA_DMA y
 else
-  if [ "$CONFIG_ARCH_EBSA285" = "y" ]; then
-    bool "PCI support" CONFIG_PCI
-  fi
+  define_bool CONFIG_ISA_DMA n
 fi
 
 # Figure out whether this system uses 26-bit or 32-bit CPUs.  Nobody has
@@ -122,6 +129,11 @@
     fi
   fi
 fi
+if [ "$CONFIG_ARCH_EBSA285" = "y" -o \
+     "$CONFIG_ARCH_EBSA110" = "y" -o \
+     "$CONFIG_ARCH_VNC" = "y" ]; then
+  string 'Initial kernel command string' CONFIG_CMDLINE
+fi
 endmenu
 
 source drivers/pnp/Config.in
@@ -132,16 +144,20 @@
   source drivers/acorn/block/Config.in
 fi
 
-source arch/arm/drivers/char/Config.in
+if [ "$CONFIG_VGA_CONSOLE" = "n" -a "$CONFIG_FB" = "n" ]; then
+  source arch/arm/drivers/char/Config.in
+else
+  source drivers/char/Config.in
+fi
+if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+  source drivers/acorn/char/Config.in
+fi
 
 if [ "$CONFIG_VT" = "y" ]; then
   mainmenu_option next_comment
   comment 'Console drivers'
   if [ "$CONFIG_ARCH_ACORN" != "y" -a "$CONFIG_ARCH_EBSA110" != "y" ]; then
     bool 'VGA text console' CONFIG_VGA_CONSOLE
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      bool 'Video mode selection support' CONFIG_VIDEO_SELECT
-    fi
   fi
   bool 'Support Frame buffer devices' CONFIG_FB
   source drivers/video/Config.in
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.1.131/linux/arch/arm/kernel/Makefile	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/Makefile	Thu Dec 17 09:05:42 1998
@@ -10,43 +10,53 @@
 
 O_TARGET := kernel.o
 O_OBJS   := $(ENTRY_OBJ) ioport.o irq.o process.o ptrace.o setup.o \
-	    signal.o sys_arm.o time.o traps.o fiq.o
+	    signal.o sys_arm.o time.o traps.o
+
+DMA_OBJS_arc      = dma-arc.o
+DMA_OBJS_a5k      = dma-a5k.o
+DMA_OBJS_rpc      = dma-rpc.o
+DMA_OBJS_ebsa110  = dma-dummy.o
+DMA_OBJS_ebsa285  = dma-ebsa285.o
+DMA_OBJS_nexuspci =
+DMA_OBJS_vnc      = dma-vnc.o
+
+O_OBJS_arc        = ecard.o iic.o fiq.o oldlatches.o
+O_OBJS_a5k        = ecard.o iic.o fiq.o
+O_OBJS_rpc        = ecard.o iic.o fiq.o
+O_OBJS_ebsa110    = leds-ebsa110.o
+O_OBJS_ebsa285    = leds-ebsa285.o hw-ebsa285.o
+O_OBJS_nexuspci   =
+O_OBJS_vnc        = leds-ebsa285.o hw-vnc.o
 
 all: lib kernel.o $(HEAD_OBJ) init_task.o
 
 ifeq ($(CONFIG_MODULES),y)
-OX_OBJS = armksyms.o
+  OX_OBJS = armksyms.o
 else
-O_OBJS += armksyms.o
+  O_OBJS += armksyms.o
 endif
 
-ifdef CONFIG_ARCH_ACORN
-  O_OBJS += ecard.o iic.o
-  ifdef CONFIG_ARCH_ARC
-    O_OBJS += oldlatches.o
+ifeq ($(MACHINE),nexuspci)
+  ifdef CONFIG_PCI
+    O_OBJS += plx9080.o
   endif
-  O_OBJS += dma-$(MACHINE).o
-  OX_OBJS += dma.o
-endif
-
-ifeq ($(MACHINE),ebsa110)
-  O_OBJS += dma-dummy.o leds-ebsa110.o
-endif
-
-ifeq ($(MACHINE),ebsa285)
-  OX_OBJS += dma.o
-  O_OBJS += dma-ebsa285.o leds-ebsa285.o
+else
   ifdef CONFIG_PCI
     O_OBJS += dec21285.o
   endif
 endif
 
-ifeq ($(MACHINE),nexuspci)
-  O_OBJS += dma-dummy.o
-  ifdef CONFIG_PCI
-    O_OBJS += plx9080.o
+ifneq ($(DMA_OBJS_$(MACHINE)),)
+  OX_OBJS += dma.o
+  O_OBJS  += $(DMA_OBJS_$(MACHINE))
+  ifeq ($(CONFIG_ISA_DMA),y)
+    O_OBJS += dma-isa.o
   endif
+else
+  O_OBJS += dma-dummy.o
 endif
+
+O_OBJS += $(O_OBJS_$(MACHINE))
 
 $(HEAD_OBJ): $(HEAD_OBJ:.o=.S)
 	$(CC) -D__ASSEMBLY__ -DTEXTADDR=$(TEXTADDR) -traditional -c $(HEAD_OBJ:.o=.S) -o $@
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/calls.S linux/arch/arm/kernel/calls.S
--- v2.1.131/linux/arch/arm/kernel/calls.S	Tue Jul 21 00:15:30 1998
+++ linux/arch/arm/kernel/calls.S	Thu Dec 17 09:05:42 1998
@@ -9,7 +9,7 @@
 #define NR_syscalls 256
 #else
 
-/* 0 */		.long	SYMBOL_NAME(sys_setup)
+/* 0 */		.long	SYMBOL_NAME(sys_ni_syscall)
 		.long	SYMBOL_NAME(sys_exit)
 		.long	SYMBOL_NAME(sys_fork_wrapper)
 		.long	SYMBOL_NAME(sys_read)
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dec21285.c linux/arch/arm/kernel/dec21285.c
--- v2.1.131/linux/arch/arm/kernel/dec21285.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/dec21285.c	Thu Dec 17 09:05:42 1998
@@ -3,14 +3,23 @@
  *
  * Copyright (C) 1998 Russell King, Phil Blundell
  */
+#include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
 #include <linux/init.h>
 
+#include <asm/irq.h>
 #include <asm/system.h>
 
 #define MAX_SLOTS		20
 
+extern void pcibios_fixup_ebsa285(struct pci_dev *dev);
+extern void pcibios_init_ebsa285(void);
+extern void pcibios_fixup_vnc(struct pci_dev *dev);
+extern void pcibios_init_vnc(void);
+
 int
 pcibios_present(void)
 {
@@ -24,12 +33,11 @@
 		int slot = PCI_SLOT(dev_fn);
 		
 		if (slot < MAX_SLOTS)
-			return 0xf8c00000 + (slot << 11);
+			return 0xf8c00000 + (slot << 11) + (PCI_FUNC(dev_fn) << 8);
 		else
 			return 0;
-	} else {
+	} else
 		return 0xf9000000 | (bus << 16) | (dev_fn << 8);
-	}
 }
 
 int
@@ -119,56 +127,35 @@
 	return PCIBIOS_SUCCESSFUL;
 }
 
-static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 };
-static int irqmap_cats[] __initdata = { 18, 8, 9, 11 };
+__initfunc(void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set))
+{
+	unsigned short cmd;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	cmd = (cmd & ~clear) | set;
+	pci_write_config_word(dev, PCI_COMMAND, cmd);
+}
 
-__initfunc(static int ebsa_irqval(struct pci_dev *dev))
+__initfunc(void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr))
 {
-	unsigned char pin;
-	
-	pcibios_read_config_byte(dev->bus->number,
-				 dev->devfn,
-				 PCI_INTERRUPT_PIN,
-				 &pin);
-	
-	return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
-}
-
-__initfunc(static int cats_irqval(struct pci_dev *dev))
-{
-	if (dev->irq >= 128)
-		return 32 + (dev->irq & 0x1f);
-
-	switch (dev->irq) {
-	case 1:
-	case 2:
-	case 3:
-	case 4:
-		return irqmap_cats[dev->irq - 1];
-	case 0:
-		return 0;
-	}
+	int reg = PCI_BASE_ADDRESS_0 + (idx << 2);
 
-	printk("PCI: device %02x:%02x has unknown irq line %x\n",
-	       dev->bus->number, dev->devfn, dev->irq);
-	return 0;
+	pci_write_config_dword(dev, reg, addr);
+	pci_read_config_dword(dev, reg, &addr);
+
+	dev->base_address[idx] = addr;
 }
 
 __initfunc(void pcibios_fixup(void))
 {
 	struct pci_dev *dev;
-	unsigned char cmd;
 
 	for (dev = pci_devices; dev; dev = dev->next) {
-		/* sort out the irq mapping for this device */
-		switch (machine_type) {
-		case MACH_TYPE_EBSA285:
-			dev->irq = ebsa_irqval(dev);
-			break;
-		case MACH_TYPE_CATS:
-			dev->irq = cats_irqval(dev);
-			break;
-		}
+		if (machine_is_ebsa285() || machine_is_cats())
+			pcibios_fixup_ebsa285(dev);
+		if (machine_is_netwinder())
+			pcibios_fixup_vnc(dev);
+
 		pcibios_write_config_byte(dev->bus->number, dev->devfn,
 					  PCI_INTERRUPT_LINE, dev->irq);
 
@@ -176,34 +163,19 @@
 		       "PCI: %02x:%02x [%04x/%04x] on irq %d\n",
 			dev->bus->number, dev->devfn,
 			dev->vendor, dev->device, dev->irq);
-
-		/* Turn on bus mastering - boot loader doesn't
-		 * - perhaps it should! - dag
-		 */
-		pcibios_read_config_byte(dev->bus->number, dev->devfn,
-					 PCI_COMMAND, &cmd);
-		cmd |= PCI_COMMAND_MASTER;
-		pcibios_write_config_byte(dev->bus->number, dev->devfn,
-					  PCI_COMMAND, cmd);
 	}
+	if (machine_is_netwinder())
+		hw_init();
 }
 
 __initfunc(void pcibios_init(void))
 {
-	int rev;
-
-	rev = *(unsigned char *)0xfe000008;
-	printk("DEC21285 PCI revision %02X\n", rev);
+	if (machine_is_ebsa285() || machine_is_cats())
+		pcibios_init_ebsa285();
+	if (machine_is_netwinder())
+		pcibios_init_vnc();
 
-	/*
-	 * Map our SDRAM at a known address in PCI space, just in case
-	 * the firmware had other ideas.  Using a nonzero base is slightly
-	 * bizarre but apparently necessary to avoid problems with some
-	 * video cards.
-	 *
-	 * We should really only do this if we are the configuration master.
-	 */
-	*((unsigned long *)0xfe000018) = 0x10000000;
+	printk("DEC21285 PCI revision %02X\n", *(unsigned char *)0xfe000008);
 }
 
 __initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dma-a5k.c linux/arch/arm/kernel/dma-a5k.c
--- v2.1.131/linux/arch/arm/kernel/dma-a5k.c	Tue Jul 21 00:15:30 1998
+++ linux/arch/arm/kernel/dma-a5k.c	Thu Dec 17 09:05:42 1998
@@ -16,7 +16,7 @@
 
 #include "dma.h"
 
-static struct fiq_handler fh = { "floppydma", NULL };
+static struct fiq_handler fh = { NULL, "floppydma", NULL, NULL };
 
 int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_id)
 {
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dma-ebsa285.c linux/arch/arm/kernel/dma-ebsa285.c
--- v2.1.131/linux/arch/arm/kernel/dma-ebsa285.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/dma-ebsa285.c	Thu Dec 17 09:05:42 1998
@@ -4,6 +4,9 @@
  * Copyright (C) 1998 Phil Blundell
  *
  * DMA functions specific to EBSA-285/CATS architectures
+ *
+ * Changelog:
+ *  09/11/1998	RMK	Split out ISA DMA functions to dma-isa.c
  */
 
 #include <linux/config.h>
@@ -19,44 +22,19 @@
 #include <asm/hardware.h>
 
 #include "dma.h"
-
-/* 8237 DMA controllers */
-#define IO_DMA1_BASE	0x00	/* 8 bit slave DMA, channels 0..3 */
-#define IO_DMA2_BASE	0xC0	/* 16 bit master DMA, ch 4(=slave input)..7 */
-
-/* 8237 DMA controller registers */
-#define DMA1_CMD_REG		0x08	/* command register (w) */
-#define DMA1_STAT_REG		0x08	/* status register (r) */
-#define DMA1_REQ_REG            0x09    /* request register (w) */
-#define DMA1_MASK_REG		0x0A	/* single-channel mask (w) */
-#define DMA1_MODE_REG		0x0B	/* mode register (w) */
-#define DMA1_CLEAR_FF_REG	0x0C	/* clear pointer flip-flop (w) */
-#define DMA1_TEMP_REG           0x0D    /* Temporary Register (r) */
-#define DMA1_RESET_REG		0x0D	/* Master Clear (w) */
-#define DMA1_CLR_MASK_REG       0x0E    /* Clear Mask */
-#define DMA1_MASK_ALL_REG       0x0F    /* all-channels mask (w) */
-
-#define DMA2_CMD_REG		0xD0	/* command register (w) */
-#define DMA2_STAT_REG		0xD0	/* status register (r) */
-#define DMA2_REQ_REG            0xD2    /* request register (w) */
-#define DMA2_MASK_REG		0xD4	/* single-channel mask (w) */
-#define DMA2_MODE_REG		0xD6	/* mode register (w) */
-#define DMA2_CLEAR_FF_REG	0xD8	/* clear pointer flip-flop (w) */
-#define DMA2_TEMP_REG           0xDA    /* Temporary Register (r) */
-#define DMA2_RESET_REG		0xDA	/* Master Clear (w) */
-#define DMA2_CLR_MASK_REG       0xDC    /* Clear Mask */
-#define DMA2_MASK_ALL_REG       0xDE    /* all-channels mask (w) */
+#include "dma-isa.h"
 
 int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
 {
-	/* 21285 internal channels */
-	if (channel == 0 || channel == 1)
+	switch (channel) {
+	case 0:
+	case 1:	/* 21285 internal channels */
 		return 0;
 
-	/* ISA channels */
-//	if (machine_is_cats() && ((channel >= 2 && channel <= 5) ||
-//		(channel >= 7 && channel <= 9)))
-//		return 0;
+	case 2 ... 9:
+		if (machine_is_cats())
+			return isa_request_dma(channel - 2, dma, dev_name);
+	}
 
 	return -EINVAL;
 }
@@ -75,14 +53,9 @@
 	case 1:
 		break;
 #ifdef CONFIG_CATS
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
+	case 2 ... 9:
+		if (machine_is_cats())
+			residue = isa_get_dma_residue(channel - 2);
 #endif
 	}
 	return residue;
@@ -98,56 +71,9 @@
 		 */
 		break;
 #ifdef CONFIG_CATS
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 7:
-	case 8:
-	case 9:
-		if (dma->invalid) {
-			static unsigned char dma_page[] = { 0x87, 0x83, 0x81, 0x82,
-							    0x00, 0x8b, 0x89, 0x8a };
-			unsigned long int address = dma->buf.address,
-				length = dma->buf.length - 1;
-			outb(address >> 24, dma_page[channel - DMA_ISA_BASE] | 0x400);
-			outb(address >> 16, dma_page[channel - DMA_ISA_BASE]);
-			if (channel >= DMA_ISA_BASE + 5) {
-				outb(0, DMA2_CLEAR_FF_REG);
-				outb(address >> 1, 
-				     IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2));
-				outb(address >> 9, 
-				     IO_DMA2_BASE + ((channel - DMA_ISA_BASE - 4) << 2));
-				outb((length >> 1) & 0xfe,
-				     IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2));
-				outb(length >> 9,
-				     IO_DMA2_BASE + 1 + ((channel - DMA_ISA_BASE - 4) << 2));
-				outb(dma->dma_mode | (channel - DMA_ISA_BASE - 4), DMA2_MODE_REG);
-			} else {
-				outb(0, DMA1_CLEAR_FF_REG);
-				outb(address >> 0, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1));
-				outb(address >> 8, IO_DMA1_BASE + ((channel - DMA_ISA_BASE) << 1));
-				outb(length >> 0,
-				     IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1));
-				outb(length >> 8,
-				     IO_DMA1_BASE + 1 + ((channel - DMA_ISA_BASE) << 1));
-				outb(dma->dma_mode | (channel - DMA_ISA_BASE), DMA1_MODE_REG);
-			}
-			switch (dma->dma_mode) {
-			case DMA_MODE_READ:
-				dma_cache_inv(__bus_to_virt(address), length + 1);
-				break;
-			case DMA_MODE_WRITE:
-				dma_cache_wback(__bus_to_virt(address), length + 1);
-				break;
-			}
-			dma->invalid = 0;
-		}
-
-		if (channel >= DMA_ISA_BASE + 5)
-			outb(channel - DMA_ISA_BASE - 4, DMA2_MASK_REG);
-		else
-			outb(channel - DMA_ISA_BASE, DMA1_MASK_REG);
+	case 2 ... 9:
+		if (machine_is_cats())
+			isa_enable_dma(channel - 2, dma);
 #endif
 	}
 }
@@ -162,18 +88,9 @@
 		 */
 		break;
 #ifdef CONFIG_CATS
-	case 2:
-	case 3:
-	case 4:
-	case 5:
-	case 6:
-	case 7:
-	case 8:
-	case 9:
-		if (channel >= DMA_ISA_BASE + 5)
-			outb(channel - DMA_ISA_BASE, DMA2_MASK_REG);
-		else
-			outb((channel - DMA_ISA_BASE) | 4, DMA1_MASK_REG);
+	case 2 ... 9:
+		if (machine_is_cats())
+			isa_disable_dma(channel - 2, dma);
 #endif
 	}
 }
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dma-isa.c linux/arch/arm/kernel/dma-isa.c
--- v2.1.131/linux/arch/arm/kernel/dma-isa.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/dma-isa.c	Thu Dec 17 09:05:42 1998
@@ -0,0 +1,107 @@
+/*
+ * arch/arm/kernel/dma-isa.c: ISA DMA primitives
+ *
+ * Copyright (C) Russell King
+ *
+ * Taken from various sources, including:
+ *  linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ *    Written by Hennus Bergman, 1992.
+ *    High DMA channel support & info by Hannu Savolainen and John Boyd, Nov. 1992.
+ *  arch/arm/kernel/dma-ebsa285.c
+ *  Copyright (C) 1998 Phil Blundell
+ */
+#include <linux/sched.h>
+
+#include <asm/dma.h>
+#include <asm/io.h>
+
+#include "dma.h"
+#include "dma-isa.h"
+
+#define ISA_DMA_MASK		0
+#define ISA_DMA_MODE		1
+#define ISA_DMA_CLRFF		2
+#define ISA_DMA_PGHI		3
+#define ISA_DMA_PGLO		4
+#define ISA_DMA_ADDR		5
+#define ISA_DMA_COUNT		6
+
+static unsigned int isa_dma_port[8][7] = {
+	/* MASK   MODE   CLRFF  PAGE_HI PAGE_LO ADDR COUNT */
+	{  0x0a,  0x0b,  0x0c,  0x487,  0x087,  0x00, 0x01 },
+	{  0x0a,  0x0b,  0x0c,  0x483,  0x083,  0x02, 0x03 },
+	{  0x0a,  0x0b,  0x0c,  0x481,  0x081,  0x04, 0x05 },
+	{  0x0a,  0x0b,  0x0c,  0x482,  0x082,  0x06, 0x07 },
+	{  0xd4,  0xd6,  0xd8,  0x000,  0x000,  0xc0, 0xc2 },
+	{  0xd4,  0xd6,  0xd8,  0x48b,  0x08b,  0xc4, 0xc6 },
+	{  0xd4,  0xd6,  0xd8,  0x489,  0x089,  0xc8, 0xca },
+	{  0xd4,  0xd6,  0xd8,  0x48a,  0x08a,  0xcc, 0xce }
+};
+
+int isa_request_dma(int channel, dma_t *dma, const char *dev_name)
+{
+	if (channel != 4)
+		return 0;
+
+	return -EINVAL;
+}
+
+void isa_free_dma(int channel, dma_t *dma)
+{
+	/* nothing to do */
+}
+
+int isa_get_dma_residue(int channel, dma_t *dma)
+{
+	unsigned int io_port = isa_dma_port[channel][ISA_DMA_COUNT];
+	int count;
+
+	count = 1 + inb(io_port) + (inb(io_port) << 8);
+
+	return channel < 4 ? count : (count << 1);
+}
+
+void isa_enable_dma(int channel, dma_t *dma)
+{
+	unsigned long address, length;
+
+	if (dma->invalid) {
+		address = dma->buf.address;
+		length  = dma->buf.length - 1;
+
+		outb(address >> 24, isa_dma_port[channel][ISA_DMA_PGHI]);
+		outb(address >> 16, isa_dma_port[channel][ISA_DMA_PGLO]);
+
+		if (channel >= 4) {
+			address >>= 1;
+			length = (length >> 1) & 0xfe; /* why &0xfe? */
+		}
+
+		outb(0, isa_dma_port[channel][ISA_DMA_CLRFF]);
+
+		outb(address, isa_dma_port[channel][ISA_DMA_ADDR]);
+		outb(address >> 8, isa_dma_port[channel][ISA_DMA_ADDR]);
+
+		outb(length, isa_dma_port[channel][ISA_DMA_COUNT]);
+		outb(length >> 8, isa_dma_port[channel][ISA_DMA_COUNT]);
+
+		outb(dma->dma_mode | (channel & 3), isa_dma_port[channel][ISA_DMA_MODE]);
+
+		switch (dma->dma_mode) {
+		case DMA_MODE_READ:
+			dma_cache_inv(__bus_to_virt(dma->buf.address), dma->buf.length);
+			break;
+
+		case DMA_MODE_WRITE:
+			dma_cache_wback(__bus_to_virt(dma->buf.address), dma->buf.length);
+			break;
+		}
+		dma->invalid = 0;
+	}
+	outb(channel & 3, isa_dma_port[channel][ISA_DMA_MASK]);
+}
+
+void isa_disable_dma(int channel, dma_t *dma)
+{
+	outb(channel | 4, isa_dma_port[channel][ISA_DMA_MASK]);
+}
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dma-isa.h linux/arch/arm/kernel/dma-isa.h
--- v2.1.131/linux/arch/arm/kernel/dma-isa.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/dma-isa.h	Thu Dec 17 09:05:42 1998
@@ -0,0 +1,25 @@
+/*
+ * Request an ISA DMA channel
+ */
+int isa_request_dma(int channel, dma_t *dma, const char *dev_name);
+
+/*
+ * Free an ISA DMA channel
+ */
+void isa_free_dma(int channel, dma_t *dma);
+
+/*
+ * Get ISA DMA channel residue
+ */
+int isa_get_dma_residue(int channel, dma_t *dma);
+
+/*
+ * Enable (and set up) an ISA DMA channel
+ */
+void isa_enable_dma(int channel, dma_t *dma);
+
+/*
+ * Disable an ISA DMA channel
+ */
+void isa_disable_dma(int channel, dma_t *dma);
+
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dma-vnc.c linux/arch/arm/kernel/dma-vnc.c
--- v2.1.131/linux/arch/arm/kernel/dma-vnc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/dma-vnc.c	Thu Dec 17 09:05:42 1998
@@ -0,0 +1,51 @@
+/*
+ * arch/arm/kernel/dma-vnc.c
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/mman.h>
+#include <linux/init.h>
+
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+
+#include "dma.h"
+#include "dma-isa.h"
+
+int arch_request_dma(dmach_t channel, dma_t *dma, const char *dev_name)
+{
+	if (channel < 8)
+		return isa_request_dma(channel, dma, dev_name);
+	return -EINVAL;
+}
+
+void arch_free_dma(dmach_t channel, dma_t *dma)
+{
+	isa_free_dma(channel, dma);
+}
+
+int arch_get_dma_residue(dmach_t channel, dma_t *dma)
+{
+	return isa_get_dma_residue(channel, dma);
+}
+
+void arch_enable_dma(dmach_t channel, dma_t *dma)
+{
+	isa_enable_dma(channel, dma);
+}
+
+void arch_disable_dma(dmach_t channel, dma_t *dma)
+{
+	isa_disable_dma(channel, dma);
+}
+
+__initfunc(void arch_dma_init(dma_t *dma))
+{
+	/* Nothing to do */
+}
+
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c
--- v2.1.131/linux/arch/arm/kernel/dma.c	Fri May  8 23:14:42 1998
+++ linux/arch/arm/kernel/dma.c	Thu Dec 17 09:05:42 1998
@@ -26,6 +26,26 @@
 #include <asm/hardware.h>
 #include <asm/io.h>
 #include <asm/dma.h>
+#include <asm/spinlock.h>
+
+
+/* A note on resource allocation:
+ *
+ * All drivers needing DMA channels, should allocate and release them
+ * through the public routines `request_dma()' and `free_dma()'.
+ *
+ * In order to avoid problems, all processes should allocate resources in
+ * the same sequence and release them in the reverse order.
+ *
+ * So, when allocating DMAs and IRQs, first allocate the IRQ, then the DMA.
+ * When releasing them, first release the DMA, then release the IRQ.
+ * If you don't, you may cause allocation requests to fail unnecessarily.
+ * This doesn't really matter now, but it will once we get real semaphores
+ * in the kernel.
+ */
+
+
+spinlock_t dma_spin_lock = SPIN_LOCK_UNLOCKED;
 
 #include "dma.h"
 
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- v2.1.131/linux/arch/arm/kernel/ecard.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/ecard.c	Thu Dec 17 09:05:42 1998
@@ -3,7 +3,7 @@
  *
  *  Find all installed expansion cards, and handle interrupts from them.
  *
- * Copyright 1995,1996,1997 Russell King
+ * Copyright 1995-1998 Russell King
  *
  * Created from information from Acorns RiscOS3 PRMs
  *
@@ -14,6 +14,7 @@
  * 29-Sep-1997	RMK	Expansion card interrupt hardware not being re-enabled on reset from
  *			Linux. (Caused cards not to respond under RiscOS without hard reset).
  * 15-Feb-1998	RMK	Added DMA support
+ * 12-Sep-1998	RMK	Added EASI support
  */
 
 #define ECARD_C
@@ -79,7 +80,7 @@
 static unsigned int ecard_numcards, ecard_numirqcards;
 static unsigned int have_expmask;
 
-static void ecard_def_irq_enable (ecard_t *ec, int irqnr)
+static void ecard_def_irq_enable(ecard_t *ec, int irqnr)
 {
 #ifdef HAS_EXPMASK
 	if (irqnr < 4 && have_expmask) {
@@ -89,7 +90,7 @@
 #endif
 }
 
-static void ecard_def_irq_disable (ecard_t *ec, int irqnr)
+static void ecard_def_irq_disable(ecard_t *ec, int irqnr)
 {
 #ifdef HAS_EXPMASK
 	if (irqnr < 4 && have_expmask) {
@@ -99,14 +100,14 @@
 #endif
 }
 
-static void ecard_def_fiq_enable (ecard_t *ec, int fiqnr)
+static void ecard_def_fiq_enable(ecard_t *ec, int fiqnr)
 {
-	panic ("ecard_def_fiq_enable called - impossible");
+	panic("ecard_def_fiq_enable called - impossible");
 }
 
-static void ecard_def_fiq_disable (ecard_t *ec, int fiqnr)
+static void ecard_def_fiq_disable(ecard_t *ec, int fiqnr)
 {
-	panic ("ecard_def_fiq_disable called - impossible");
+	panic("ecard_def_fiq_disable called - impossible");
 }
 
 static expansioncard_ops_t ecard_default_ops = {
@@ -122,7 +123,7 @@
  *
  * They are not meant to be called directly, but via enable/disable_irq.
  */
-void ecard_enableirq (unsigned int irqnr)
+void ecard_enableirq(unsigned int irqnr)
 {
 	irqnr &= 7;
 	if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
@@ -132,14 +133,14 @@
 			ec->ops = &ecard_default_ops;
 
 		if (ec->claimed && ec->ops->irqenable)
-			ec->ops->irqenable (ec, irqnr);
+			ec->ops->irqenable(ec, irqnr);
 		else
-			printk (KERN_ERR "ecard: rejecting request to "
+			printk(KERN_ERR "ecard: rejecting request to "
 				"enable IRQs for %d\n", irqnr);
 	}
 }
 
-void ecard_disableirq (unsigned int irqnr)
+void ecard_disableirq(unsigned int irqnr)
 {
 	irqnr &= 7;
 	if (irqnr < MAX_ECARDS && irqno_to_expcard[irqnr] != -1) {
@@ -149,11 +150,11 @@
 			ec->ops = &ecard_default_ops;
 
 		if (ec->ops && ec->ops->irqdisable)
-			ec->ops->irqdisable (ec, irqnr);
+			ec->ops->irqdisable(ec, irqnr);
 	}
 }
 
-void ecard_enablefiq (unsigned int fiqnr)
+void ecard_enablefiq(unsigned int fiqnr)
 {
 	fiqnr &= 7;
 	if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
@@ -163,14 +164,14 @@
 			ec->ops = &ecard_default_ops;
 
 		if (ec->claimed && ec->ops->fiqenable)
-			ec->ops->fiqenable (ec, fiqnr);
+			ec->ops->fiqenable(ec, fiqnr);
 		else
-			printk (KERN_ERR "ecard: rejecting request to "
+			printk(KERN_ERR "ecard: rejecting request to "
 				"enable FIQs for %d\n", fiqnr);
 	}
 }
 
-void ecard_disablefiq (unsigned int fiqnr)
+void ecard_disablefiq(unsigned int fiqnr)
 {
 	fiqnr &= 7;
 	if (fiqnr < MAX_ECARDS && irqno_to_expcard[fiqnr] != -1) {
@@ -180,7 +181,7 @@
 			ec->ops = &ecard_default_ops;
 
 		if (ec->ops->fiqdisable)
-			ec->ops->fiqdisable (ec, fiqnr);
+			ec->ops->fiqdisable(ec, fiqnr);
 	}
 }
 
@@ -198,8 +199,27 @@
 		}
 	}
 	cli();
-	if (called == 0)
-		printk (KERN_WARNING "Wild interrupt from backplane?\n");
+	if (called == 0) {
+		static int last, lockup;
+
+		if (last == jiffies) {
+			lockup += 1;
+			if (lockup > 1000000) {
+				printk(KERN_ERR "\nInterrupt lockup detected - disabling expansion card IRQs\n");
+				disable_irq(intr_no);
+				printk("Expansion card IRQ state:\n");
+				for (i = 0; i < num_cards; i++)
+					printk("  %d: %sclaimed, irqaddr = %p, irqmask = %X, status=%X\n", expcard[i].irq - 32,
+						expcard[i].claimed ? "" : "not", expcard[i].irqaddr, expcard[i].irqmask, *expcard[i].irqaddr);
+			}
+		} else
+			lockup = 0;
+
+		if (!last || last + 500 < jiffies) {
+			last = jiffies;
+			printk(KERN_ERR "\nUnrecognised interrupt from backplane\n");
+		}
+	}
 }
 
 #ifdef HAS_EXPMASK
@@ -214,7 +234,7 @@
 	0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00
 };
 
-static void ecard_irq_expmask (int intr_no, void *dev_id, struct pt_regs *regs)
+static void ecard_irq_expmask(int intr_no, void *dev_id, struct pt_regs *regs)
 {
 	const unsigned int statusmask = 15;
 	unsigned int status;
@@ -239,22 +259,22 @@
 			 */
 			oldexpmask = have_expmask;
 			EXPMASK_ENABLE = (have_expmask &= priority_masks[irqno]);
-			sti ();
-			do_ecard_IRQ (ec->irq, regs);
-			cli ();
+			sti();
+			do_ecard_IRQ(ec->irq, regs);
+			cli();
 			EXPMASK_ENABLE = have_expmask = oldexpmask;
 			status = EXPMASK_STATUS & statusmask;
 			if (status)
 				goto again;
 		} else {
-			printk (KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno);
+			printk(KERN_WARNING "card%d: interrupt from unclaimed card???\n", irqno);
 			EXPMASK_ENABLE = (have_expmask &= ~(1 << irqno));
 		}
 	} else
-		printk (KERN_WARNING "Wild interrupt from backplane (masks)\n");
+		printk(KERN_WARNING "Wild interrupt from backplane (masks)\n");
 }
 
-static int ecard_checkirqhw (void)
+static int ecard_checkirqhw(void)
 {
 	int found;
 
@@ -267,7 +287,7 @@
 }
 #endif
 
-static void ecard_readbytes (void *addr, ecard_t *ec, int off, int len, int useld)
+static void ecard_readbytes(void *addr, ecard_t *ec, int off, int len, int useld)
 {
 	extern int ecard_loader_read(int off, volatile unsigned int pa, loader_t loader);
 	unsigned char *a = (unsigned char *)addr;
@@ -287,7 +307,7 @@
 		 * If we require a low address or address 0, then reset, and start again...
 		 */
 		if (!off || lowaddress > laddr) {
-			outb (0, ec->podaddr);
+			outb(0, ec->podaddr);
 			lowaddress = 0;
 		}
 		while (lowaddress <= laddr) {
@@ -314,15 +334,136 @@
 	}
 }
 
+static int ecard_prints(char *buffer, ecard_t *ec)
+{
+	char *start = buffer;
+
+	buffer += sprintf(buffer, "\n  %d: ", ec->slot_no);
+
+	if (ec->cid.id == 0) {
+		struct in_chunk_dir incd;
+
+		buffer += sprintf(buffer, "[%04X:%04X] ",
+			ec->cid.manufacturer, ec->cid.product);
+
+		if (!ec->card_desc && ec->cid.is && ec->cid.cd &&
+		    ecard_readchunk(&incd, ec, 0xf5, 0))
+			ec->card_desc = incd.d.string;
+
+		if (!ec->card_desc)
+			ec->card_desc = "*unknown*";
+
+		buffer += sprintf(buffer, "%s", ec->card_desc);
+	} else
+		buffer += sprintf(buffer, "Simple card %d", ec->cid.id);
+
+	return buffer - start;
+}
+
+static inline unsigned short ecard_getu16(unsigned char *v)
+{
+	return v[0] | v[1] << 8;
+}
+
+static inline signed long ecard_gets24(unsigned char *v)
+{
+	return v[0] | v[1] << 8 | v[2] << 16 | ((v[2] & 0x80) ? 0xff000000 : 0);
+}
+
+/*
+ * Probe for an expansion card.
+ *
+ * If bit 1 of the first byte of the card is set, then the
+ * card does not exist.
+ */
+__initfunc(static int ecard_probe(int card, int freeslot, card_type_t type))
+{
+	ecard_t *ec = expcard + freeslot;
+	struct ex_ecid cid;
+	char buffer[200];
+	int i;
+
+	irqno_to_expcard[card] = -1;
+
+	ec->slot_no	= card;
+	ec->irq		= NO_IRQ;
+	ec->fiq		= NO_IRQ;
+	ec->dma		= NO_DMA;
+	ec->card_desc	= NULL;
+	ec->ops		= &ecard_default_ops;
+
+	if ((ec->podaddr = ecard_address(ec, type, ECARD_SYNC)) == 0)
+		return 0;
+
+	cid.r_zero = 1;
+	ecard_readbytes(&cid, ec, 0, 16, 0);
+	if (cid.r_zero)
+		return 0;
+
+	irqno_to_expcard[card] = freeslot;
+
+	ec->type	= type;
+	ec->cid.id	= cid.r_id;
+	ec->cid.cd	= cid.r_cd;
+	ec->cid.is	= cid.r_is;
+	ec->cid.w	= cid.r_w;
+	ec->cid.manufacturer = ecard_getu16(cid.r_manu);
+	ec->cid.product = ecard_getu16(cid.r_prod);
+	ec->cid.country = cid.r_country;
+	ec->cid.irqmask = cid.r_irqmask;
+	ec->cid.irqoff  = ecard_gets24(cid.r_irqoff);
+	ec->cid.fiqmask = cid.r_fiqmask;
+	ec->cid.fiqoff  = ecard_gets24(cid.r_fiqoff);
+	ec->fiqaddr	=
+	ec->irqaddr	= (unsigned char *)BUS_ADDR(ec->podaddr);
+
+	if (ec->cid.cd && ec->cid.is) {
+		ec->irqmask = ec->cid.irqmask;
+		ec->irqaddr += ec->cid.irqoff;
+		ec->fiqmask = ec->cid.fiqmask;
+		ec->fiqaddr += ec->cid.fiqoff;
+	} else {
+		ec->irqmask = 1;
+		ec->fiqmask = 4;
+	}
+
+	for (i = 0; i < sizeof(blacklist) / sizeof(*blacklist); i++)
+		if (blacklist[i].manufacturer == ec->cid.manufacturer &&
+		    blacklist[i].product == ec->cid.product) {
+			ec->loader = blacklist[i].loader;
+			ec->card_desc = blacklist[i].type;
+			break;
+		}
+
+	ecard_prints(buffer, ec);
+	printk("%s", buffer);
+
+	ec->irq = 32 + card;
+#ifdef IO_EC_MEMC8_BASE
+	if (card == 8)
+		ec->irq = 11;
+#endif
+#ifdef CONFIG_ARCH_RPC
+	/* On RiscPC, only first two slots have DMA capability */
+	if (card < 2)
+		ec->dma = 2 + card;
+#endif
+#if 0	/* We don't support FIQs on expansion cards at the moment */
+	ec->fiq = 96 + card;
+#endif
+
+	return 1;
+}
+
 /*
  * This is called to reset the loaders for each expansion card on reboot.
  *
  * This is required to make sure that the card is in the correct state
  * that RiscOS expects it to be.
  */
-void ecard_reset (int card)
+void ecard_reset(int card)
 {
-	extern int ecard_loader_reset (volatile unsigned int pa, loader_t loader);
+	extern int ecard_loader_reset(volatile unsigned int pa, loader_t loader);
 
 	if (card >= ecard_numcards)
 		return;
@@ -330,11 +471,11 @@
 	if (card < 0) {
 		for (card = 0; card < ecard_numcards; card++)
 			if (expcard[card].loader)
-				ecard_loader_reset (BUS_ADDR(expcard[card].podaddr),
+				ecard_loader_reset(BUS_ADDR(expcard[card].podaddr),
 							expcard[card].loader);
 	} else
 		if (expcard[card].loader)
-			ecard_loader_reset (BUS_ADDR(expcard[card].podaddr),
+			ecard_loader_reset(BUS_ADDR(expcard[card].podaddr),
 						expcard[card].loader);
 
 #ifdef HAS_EXPMASK
@@ -347,18 +488,19 @@
 
 static unsigned int ecard_startcard;
 
-void ecard_startfind (void)
+void ecard_startfind(void)
 {
 	ecard_startcard = 0;
 }
 
-ecard_t *ecard_find (int cld, const card_ids *cids)
+ecard_t *ecard_find(int cid, const card_ids *cids)
 {
 	int card;
+
 	if (!cids) {
 		for (card = ecard_startcard; card < ecard_numcards; card++)
 			if (!expcard[card].claimed &&
-			    ((expcard[card].cld.ecld ^ cld) & 0x78) == 0)
+			    (expcard[card].cid.id ^ cid) == 0)
 				break;
 	} else {
 		for (card = ecard_startcard; card < ecard_numcards; card++) {
@@ -368,8 +510,8 @@
 			if (expcard[card].claimed)
 				continue;
 
-			manufacturer = expcard[card].cld.manufacturer;
-			product = expcard[card].cld.product;
+			manufacturer = expcard[card].cid.manufacturer;
+			product = expcard[card].cid.product;
 
 			for (i = 0; cids[i].manufacturer != 65535; i++)
 				if (manufacturer == cids[i].manufacturer &&
@@ -380,16 +522,21 @@
 				break;
 		}
 	}
+
 	ecard_startcard = card + 1;
+
 	return card < ecard_numcards ? &expcard[card] : NULL;
 }
 
-int ecard_readchunk (struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
+int ecard_readchunk(struct in_chunk_dir *cd, ecard_t *ec, int id, int num)
 {
 	struct ex_chunk_dir excd;
 	int index = 16;
 	int useld = 0;
 
+	if (!ec->cid.is || !ec->cid.cd)
+		return 0;
+
 	while(1) {
 		ecard_readbytes(&excd, ec, index, 8, useld);
 		index += 8;
@@ -427,124 +574,49 @@
 		}
 	}
 	cd->start_offset = c_start(&excd);
-	memcpy (cd->d.string, excd.d.string, 256);
+	memcpy(cd->d.string, excd.d.string, 256);
 	return 1;
 }
 
-unsigned int ecard_address (ecard_t *ec, card_type_t type, card_speed_t speed)
+unsigned int ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed)
 {
 	switch (ec->slot_no) {
 	case 0 ... 3:
 		switch (type) {
 		case ECARD_MEMC:
-			return MEMCECIO_BASE + (ec->slot_no << 12);
+			return IO_EC_MEMC_BASE + (ec->slot_no << 12);
 
 		case ECARD_IOC:
-			return IOCECIO_BASE + (speed << 17) + (ec->slot_no << 12);
+			return IO_EC_IOC_BASE + (speed << 17) + (ec->slot_no << 12);
 
-		default:
-			return 0;
+#ifdef IO_EC_EASI_BASE
+		case ECARD_EASI:
+			return IO_EC_EASI_BASE + (ec->slot_no << 22);
+#endif
 		}
+		break;
 
-#ifdef IOCEC4IO_BASE
 	case 4 ... 7:
-		if (type != ECARD_IOC)
-			return 0;
-
-		return IOCEC4IO_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
+		switch (type) {
+#ifdef IO_EC_IOC4_BASE
+		case ECARD_IOC:
+			return IO_EC_IOC4_BASE + (speed << 17) + ((ec->slot_no - 4) << 12);
 #endif
-#ifdef MEMCEC8IO_BASE
-	case 8:
-		return MEMCEC8IO_BASE;
+#ifdef IO_EC_EASI_BASE
+		case ECARD_EASI:
+			return IO_EC_EASI_BASE + (ec->slot_no << 22);
 #endif
-	}
-	return 0;
-}
-
-/*
- * Probe for an expansion card.
- *
- * If bit 1 of the first byte of the card is set,
- * then the card does not exist.
- */
-__initfunc(static int ecard_probe (int card, int freeslot))
-{
-	ecard_t *ec = expcard + freeslot;
-	struct ex_ecld excld;
-	const char *card_desc = NULL;
-	int i;
-
-	irqno_to_expcard[card] = -1;
-
-	ec->slot_no = card;
-	if ((ec->podaddr = ecard_address (ec, ECARD_IOC, ECARD_SYNC)) == 0)
-		return 0;
-
-	excld.r_ecld = 2;
-	ecard_readbytes (&excld, ec, 0, 16, 0);
-	if (excld.r_ecld & 2)
-		return 0;
-
-	irqno_to_expcard[card] = freeslot;
-
-	ec->irq = NO_IRQ;
-	ec->fiq = NO_IRQ;
-	ec->dma = NO_DMA;
-	ec->cld.ecld = e_ecld(&excld);
-	ec->cld.manufacturer = e_manu(&excld);
-	ec->cld.product = e_prod(&excld);
-	ec->cld.country = e_country(&excld);
-	ec->cld.fiqmask = e_fiqmask(&excld);
-	ec->cld.irqmask = e_irqmask(&excld);
-	ec->cld.fiqaddr = e_fiqaddr(&excld);
-	ec->cld.irqaddr = e_irqaddr(&excld);
-	ec->fiqaddr =
-	ec->irqaddr = (unsigned char *)BUS_ADDR(ec->podaddr);
-	ec->fiqmask = 4;
-	ec->irqmask = 1;
-	ec->ops = &ecard_default_ops;
-
-	for (i = 0; i < sizeof (blacklist) / sizeof (*blacklist); i++)
-		if (blacklist[i].manufacturer == ec->cld.manufacturer &&
-		    blacklist[i].product == ec->cld.product) {
-			ec->loader = blacklist[i].loader;
-			card_desc = blacklist[i].type;
+		default:
 			break;
 		}
+		break;
 
-	ec->irq = 32 + card;
-#if 0
-	/* We don't support FIQs on expansion cards at the moment */
-	ec->fiq = 96 + card;
-#endif
-#ifdef CONFIG_ARCH_RPC
-	if (card != 8) {
-		/* On RiscPC, only first two slots have DMA capability
-		 */
-		if (card < 2)
-			ec->dma = 2 + card;
-	} else
-		ec->irq = 11;
+#ifdef IO_EC_MEMC8_BASE
+	case 8:
+		return IO_EC_MEMC8_BASE;
 #endif
-
-	if ((ec->cld.ecld & 0x78) == 0) {
-		struct in_chunk_dir incd;
-		printk ("\n  %d: [%04X:%04X] ", card, ec->cld.manufacturer, ec->cld.product);
-		if (e_is (&excld)) {
-			ec->fiqmask = e_fiqmask (&excld);
-			ec->irqmask = e_irqmask (&excld);
-			ec->fiqaddr += e_fiqaddr (&excld);
-			ec->irqaddr += e_irqaddr (&excld);
-		}
-		if (!card_desc && e_cd (&excld) && ecard_readchunk (&incd, ec, 0xf5, 0))
-			card_desc = incd.d.string;
-		if (card_desc)
-			printk ("%s", card_desc);
-		else
-			printk ("*Unknown*");
-	} else
-		printk("\n  %d: Simple card %d\n", card, (ec->cld.ecld >> 3) & 15);
-	return 1;
+	}
+	return 0;
 }
 
 static struct irqaction irqexpansioncard = {
@@ -565,11 +637,11 @@
 {
 	int i, nc = 0;
 
-	memset (expcard, 0, sizeof (expcard));
+	memset(expcard, 0, sizeof(expcard));
 
 #ifdef HAS_EXPMASK
 	if (ecard_checkirqhw()) {
-		printk (KERN_DEBUG "Expansion card interrupt management hardware found\n");
+		printk(KERN_DEBUG "Expansion card interrupt management hardware found\n");
 		irqexpansioncard.handler = ecard_irq_expmask;
 		irqexpansioncard.flags |= SA_IRQNOMASK;
 		have_expmask = -1;
@@ -581,8 +653,8 @@
 	/*
 	 * First of all, probe all cards on the expansion card interrupt line
 	 */
-	for (i = 0; i < 4; i++)
-		if (ecard_probe (i, nc))
+	for (i = 0; i < 8; i++)
+		if (ecard_probe(i, nc, ECARD_IOC) || ecard_probe(i, nc, ECARD_EASI))
 			nc += 1;
 		else
 			have_expmask &= ~(1<<i);
@@ -591,8 +663,8 @@
 
 	/* Now probe other cards with different interrupt lines
 	 */
-#ifdef MEMCEC8IO_BASE
-	if (ecard_probe (8, nc))
+#ifdef IO_EC_MEMC8_BASE
+	if (ecard_probe(8, nc, ECARD_IOC))
 		nc += 1;
 #endif
 
@@ -600,7 +672,7 @@
 	ecard_numcards = nc;
 
 	if (nc && setup_arm_irq(IRQ_EXPANSIONCARD, &irqexpansioncard)) {
-		printk ("Could not allocate interrupt for expansion cards\n");
+		printk("Could not allocate interrupt for expansion cards\n");
 		return;
 	}
 	
@@ -609,5 +681,5 @@
 		EXPMASK_ENABLE = have_expmask;
 #endif
 
-	oldlatch_init ();
+	oldlatch_init();
 }
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S
--- v2.1.131/linux/arch/arm/kernel/entry-armo.S	Sun Jun  7 11:16:26 1998
+++ linux/arch/arm/kernel/entry-armo.S	Thu Dec 17 09:05:42 1998
@@ -271,26 +271,18 @@
 		mov	fp, #0
 		teqp	pc, #I_BIT | MODE_SVC
 .Lbug_undef:
-		adr	r1, .LC2
-		ldmia	r1, {r1, r4}
-		ldr	r1, [r1]
-		get_current_task r2
-		teq	r1, r2
-		stmnefd	sp!, {ip, lr}
-		blne	SYMBOL_NAME(math_state_restore)
-		ldmnefd	sp!, {ip, lr}
+		ldr	r4, .LC2
 		ldr	pc, [r4]			@ Call FP module USR entry point
 
 		.globl	SYMBOL_NAME(fpundefinstr)
 SYMBOL_NAME(fpundefinstr):				@ Called by FP module on undefined instr
-SYMBOL_NAME(fpundefinstrsvc):
 		mov	r0, lr
 		mov	r1, sp
 		teqp	pc, #MODE_SVC
 		bl	SYMBOL_NAME(do_undefinstr)
 		b	ret_from_exception		@ Normal FP exit
 
-__und_svc:	SVC_SAVE_ALL			@ Non-user mode
+__und_svc:	SVC_SAVE_ALL				@ Non-user mode
 		mask_pc	r0, lr
 		and	r2, lr, #3
 		sub	r0, r0, #4
@@ -298,8 +290,44 @@
 		bl	SYMBOL_NAME(do_undefinstr)
 		SVC_RESTORE_ALL
 
-.LC2:		.word	SYMBOL_NAME(last_task_used_math)
-		.word	SYMBOL_NAME(fp_enter)
+/* We get here if an undefined instruction happens and the floating
+ * point emulator is not present.  If the offending instruction was
+ * a WFS, we just perform a normal return as if we had emulated the
+ * operation.  This is a hack to allow some basic userland binaries
+ * to run so that the emulator module proper can be loaded. --philb
+ */
+fpe_not_present:
+		adr	r10, wfs_mask_data
+		ldmia	r10, {r4, r5, r6, r7, r8}
+		ldr	r10, [sp, #S_PC]		@ Load PC
+		sub	r10, r10, #4
+		mask_pc	r10, r10
+		ldrt	r10, [r10]			@ get instruction
+		and	r5, r10, r5
+		teq	r5, r4				@ Is it WFS?
+		beq	ret_from_exception
+		and	r5, r10, r8
+		teq	r5, r6				@ Is it LDF/STF on sp or fp?
+		teqne	r5, r7
+		bne	fpundefinstr
+		tst	r10, #0x00200000		@ Does it have WB
+		beq	ret_from_exception
+		and	r4, r10, #255			@ get offset
+		and	r6, r10, #0x000f0000
+		tst	r10, #0x00800000		@ +/-
+		rsbeq	r4, r4, #0
+		ldr	r5, [sp, r6, lsr #14]		@ Load reg
+		add	r5, r5, r4, lsl #2
+		str	r5, [sp, r6, lsr #14]		@ Save reg
+		b	ret_from_exception
+
+wfs_mask_data:	.word	0x0e200110			@ WFS
+		.word	0x0fff0fff
+		.word	0x0d0d0100			@ LDF [sp]/STF [sp]
+		.word	0x0d0b0100			@ LDF [fp]/STF [fp]
+		.word	0x0f0f0f00
+
+.LC2:		.word	SYMBOL_NAME(fp_enter)
 
 /*=============================================================================
  * Prefetch abort handler
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
--- v2.1.131/linux/arch/arm/kernel/entry-armv.S	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/entry-armv.S	Thu Dec 17 09:05:42 1998
@@ -231,60 +231,68 @@
 		.macro	disable_fiq
 		.endm
 
+		.equ	pci_iack_high, PCI_IACK & 0xff000000
+		.equ	pci_iack_low,  PCI_IACK & 0x00ff0000
+
 		.macro	get_irqnr_and_base, irqnr, irqstat, base
 		mov	r4, #IO_BASE_ARM_CSR
-		ldr	\irqstat, [r4, #IRQ_STATUS]	@ just show us the unmasked ones
+		ldr	\irqstat, [r4, #CSR_IRQ_STATUS]	@ just show us the unmasked ones
 
 		@ run through hard priorities
 		@ timer
 		tst	\irqstat, #IRQ_MASK_TIMER0
 		movne	\irqnr, #IRQ_TIMER0
-		bne	1f
+		bne	1001f
 
 		@ ether10
 		tst	\irqstat, #IRQ_MASK_ETHER10
 		movne	\irqnr, #IRQ_ETHER10
-		bne	1f
+		bne	1001f
 
 		@ ether100
 		tst	\irqstat, #IRQ_MASK_ETHER100
 		movne	\irqnr, #IRQ_ETHER100
-		bne	1f
+		bne	1001f
 
 		@ video compressor
-		tst	\irqstat, #IRQ_VIDCOMP_MASK
+		tst	\irqstat, #IRQ_MASK_VIDCOMP
 		movne	\irqnr, #IRQ_VIDCOMP
-		bne	1f
+		bne	1001f
 
 		@ now try all the PIC sources
 		@ determine whether we have an irq
 		tst	\irqstat, #IRQ_MASK_EXTERN_IRQ
-		beq	3f
-		mov	r4, #(IO_BASE_PCI_IACK & 0xff000000)
-		orr	r4, r4, #(IO_BASE_PCI_IACK & 0x00ff0000)
+		beq	1002f
+		mov	r4, #pci_iack_high
+		orr	r4, r4, #pci_iack_low
 		ldrb	\irqnr, [r4]			@ get the IACK byte
-		b	1f
+		b	1001f
 
-3:		@ PCI errors
+1002:		@ PCI errors
 		tst	\irqstat, #IRQ_MASK_PCI_ERR
 		movne	\irqnr, #IRQ_PCI_ERR
-		bne	1f
+		bne	1001f
 
 		@ softint
-		tst	\irqstat, #IRQ_MASK_SOFT_IRQ
-		movne	\irqnr, #IRQ_SOFT_IRQ
-		bne	1f
+		tst	\irqstat, #IRQ_MASK_SOFTIRQ
+		movne	\irqnr, #IRQ_SOFTIRQ
+		bne	1001f
 
 		@ debug uart
 		tst	\irqstat, #IRQ_MASK_UART_DEBUG
-		movne	\irqnr, #IRQ_UART_DEBUG
-		bne	1f
+		movne	\irqnr, #IRQ_CONRX
+		bne	1001f
 
 		@ watchdog
-		tst	\irqstat, #IRQ_WATCHDOG_MASK
+		tst	\irqstat, #IRQ_MASK_WATCHDOG
 		movne	\irqnr, #IRQ_WATCHDOG
 
-1:		@ If Z is set, then we will not enter an interrupt
+1001:		@ If Z is set, then we will not enter an interrupt
+		.endm
+
+		.macro	irq_prio_table
+		.endm
+
 #else
 #error Unknown architecture
 #endif
@@ -696,8 +704,8 @@
 		adrsvc	al, lr, fpundefinstr		@ lr  = undefined instr return
 
 1:		get_current_task r10
-		mov	lr, #1
-		strb	lr, [r10, #TSK_USED_MATH]	@ set current->used_math
+		mov	r8, #1
+		strb	r8, [r10, #TSK_USED_MATH]	@ set current->used_math
 		add	r10, r10, #TSS_FPESAVE		@ r10 = workspace
 		ldr	r4, .LC2
 		ldr	pc, [r4]			@ Call FP module USR entry point
@@ -741,6 +749,43 @@
 		mov	r1, #BAD_UNDEFINSTR		@ int reason
 		and	r2, r6, #31			@ int mode
 		b	SYMBOL_NAME(bad_mode)		@ Does not ever return...
+
+/* We get here if an undefined instruction happens and the floating
+ * point emulator is not present.  If the offending instruction was
+ * a WFS, we just perform a normal return as if we had emulated the
+ * operation.  This is a hack to allow some basic userland binaries
+ * to run so that the emulator module proper can be loaded. --philb
+ */
+fpe_not_present:
+		adr	r10, wfs_mask_data
+		ldmia	r10, {r4, r5, r6, r7, r8}
+		ldr	r10, [sp, #S_PC]		@ Load PC
+		sub	r10, r10, #4
+		mask_pc	r10, r10
+		ldrt	r10, [r10]			@ get instruction
+		and	r5, r10, r5
+		teq	r5, r4				@ Is it WFS?
+		moveq	pc, r9
+		and	r5, r10, r8
+		teq	r5, r6				@ Is it LDF/STF on sp or fp?
+		teqne	r5, r7
+		movne	pc, lr
+		tst	r10, #0x00200000		@ Does it have WB
+		moveq	pc, r9
+		and	r4, r10, #255			@ get offset
+		and	r6, r10, #0x000f0000
+		tst	r10, #0x00800000		@ +/-
+		rsbeq	r4, r4, #0
+		ldr	r5, [sp, r6, lsr #14]		@ Load reg
+		add	r5, r5, r4, lsl #2
+		str	r5, [sp, r6, lsr #14]		@ Save reg
+		mov	pc, r9
+
+wfs_mask_data:	.word	0x0e200110			@ WFS
+		.word	0x0fff0fff
+		.word	0x0d0d0100			@ LDF [sp]/STF [sp]
+		.word	0x0d0b0100			@ LDF [fp]/STF [fp]
+		.word	0x0f0f0f00
 
 #include "entry-common.S"
 
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/entry-common.S linux/arch/arm/kernel/entry-common.S
--- v2.1.131/linux/arch/arm/kernel/entry-common.S	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/entry-common.S	Thu Dec 17 09:05:42 1998
@@ -288,4 +288,4 @@
 		.data
 
 ENTRY(fp_enter)
-		.word	fpundefinstr
+		.word	fpe_not_present
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c
--- v2.1.131/linux/arch/arm/kernel/fiq.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/fiq.c	Thu Dec 17 09:05:42 1998
@@ -106,14 +106,7 @@
 	memcpy((void *)FIQ_VECTOR, start, length);
 
 	protect_page_0();
-#if 0
-	/* This doesn'w work correctly.  Ok, it's a misuse
-	 * of the DMA flushing code, but it ought to work.
-	 * More investigation required.  Maybe it really
-	 * needs the cache flushed.
-	 */
-	dma_cache_wback(FIQ_VECTOR, length);
-#else
+#ifdef CONFIG_CPU_32
 	processor.u.armv3v4._flush_cache_area(FIQ_VECTOR, FIQ_VECTOR + length, 1);
 #endif
 }
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/head-armo.S linux/arch/arm/kernel/head-armo.S
--- v2.1.131/linux/arch/arm/kernel/head-armo.S	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/head-armo.S	Thu Dec 17 09:05:42 1998
@@ -58,6 +58,3 @@
 		cmp	r4, r3
 		blt	1b
 		movs	pc, lr
-
-		.align	13
-ENTRY(this_must_match_init_task)
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/head-armv.S linux/arch/arm/kernel/head-armv.S
--- v2.1.131/linux/arch/arm/kernel/head-armv.S	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/head-armv.S	Thu Dec 17 09:05:42 1998
@@ -8,9 +8,23 @@
 #include <linux/config.h>
 #include <linux/linkage.h>
 
+#ifndef CONFIG_ARCH_VNC
 #if (TEXTADDR & 0xffff) != 0x8000
 #error TEXTADDR must start at 0xXXXX8000
 #endif
+#else
+		.text
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, r0
+		mov	r0, #0
+		mov	r1, #5
+#endif
 
 #define DEBUG
 
@@ -97,6 +111,15 @@
 		add	r3, r3, #1 << 20
 		teq	r0, r2
 		bne	1b
+#ifdef CONFIG_ARCH_VNC
+		add	r0, r4, #0x3f00
+		add	r0, r0, #0x00f8
+		mov	r3, #0x7c000000
+		orr	r3, r3, r8
+		str	r3, [r0], #4
+		add	r3, r3, #1 << 20
+		str	r3, [r0], #4
+#endif
 #endif
 #ifdef CONFIG_ARCH_RPC
 /* Map in screen at 0x02000000 & SCREEN2_BASE
@@ -339,7 +362,7 @@
 		beq	1001b
 		.endm
 
-#elif defined(CONFIG_ARCH_EBSA285) || defined(CONFIG_ARCH_VNC)
+#elif defined(CONFIG_ARCH_EBSA285)
 		.macro	addruart,rx
 		mov	\rx, #0xfe000000
 		.endm
@@ -373,6 +396,30 @@
 		.endm
 
 		.macro	waituart,rd,rx
+		.endm
+
+#elif defined(CONFIG_ARCH_VNC)
+		.macro	addruart,rx
+		mov	\rx, #0xff000000
+		orr	\rx, \rx, #0x00e00000
+		orr	\rx, \rx, #0x000003f8
+		.endm
+
+		.macro	senduart,rd,rx
+		strb	\rd, [\rx]
+		.endm
+
+		.macro	busyuart,rd,rx
+1002:		ldrb	\rd, [\rx, #0x5]
+		and	\rd, \rd, #0x60
+		teq	\rd, #0x60
+		bne	1002b
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldrb	\rd, [\rx, #0x6]
+		tst	\rd, #0x10
+		beq	1001b
 		.endm
 #else
 #error Unknown architecture
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/hw-ebsa285.c linux/arch/arm/kernel/hw-ebsa285.c
--- v2.1.131/linux/arch/arm/kernel/hw-ebsa285.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/kernel/hw-ebsa285.c	Thu Dec 17 09:05:42 1998
@@ -0,0 +1,161 @@
+/*
+ * arch/arm/kernel/hw-ebsa286.c
+ *
+ * EBSA285 hardware specific functions
+ *
+ * Copyright (C) 1998 Russell King, Phil Blundel
+ */
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+
+#include <asm/irq.h>
+#include <asm/system.h>
+
+extern int setup_arm_irq(int, struct irqaction *);
+
+extern void pci_set_cmd(struct pci_dev *dev, unsigned short clear, unsigned short set);
+extern void pci_set_base_addr(struct pci_dev *dev, int idx, unsigned int addr);
+extern void pci_set_irq_line(struct pci_dev *dev, unsigned int irq);
+
+static int irqmap_ebsa[] __initdata = { 9, 8, 18, 11 };
+static int irqmap_cats[] __initdata = { 18, 8, 9, 11 };
+
+__initfunc(static int ebsa_irqval(struct pci_dev *dev))
+{
+	unsigned char pin;
+	
+	pcibios_read_config_byte(dev->bus->number,
+				 dev->devfn,
+				 PCI_INTERRUPT_PIN,
+				 &pin);
+	
+	return irqmap_ebsa[(PCI_SLOT(dev->devfn) + pin) & 3];
+}
+
+__initfunc(static int cats_irqval(struct pci_dev *dev))
+{
+	if (dev->irq >= 128)
+		return 32 + (dev->irq & 0x1f);
+
+	switch (dev->irq) {
+	case 1:
+	case 2:
+	case 3:
+	case 4:
+		return irqmap_cats[dev->irq - 1];
+	case 0:
+		return 0;
+	}
+
+	printk("PCI: device %02x:%02x has unknown irq line %x\n",
+	       dev->bus->number, dev->devfn, dev->irq);
+	return 0;
+}
+
+__initfunc(void pcibios_fixup_ebsa285(struct pci_dev *dev))
+{
+	char cmd;
+
+	/* sort out the irq mapping for this device */
+	switch (machine_type) {
+	case MACH_TYPE_EBSA285:
+		dev->irq = ebsa_irqval(dev);
+		break;
+	case MACH_TYPE_CATS:
+		dev->irq = cats_irqval(dev);
+		break;
+	}
+
+	/* Turn on bus mastering - boot loader doesn't
+	 * - perhaps it should! - dag
+	 */
+	pci_read_config_byte(dev, PCI_COMMAND, &cmd);
+	pci_write_config_byte(dev, PCI_COMMAND, cmd | PCI_COMMAND_MASTER);
+}
+
+static void irq_pci_err(int irq, void *dev_id, struct pt_regs *regs)
+{
+	const char *err = "unknown";
+	unsigned long cmd = *(unsigned long *)0xfe000004 & 0xffff;
+	unsigned long ctrl = *(unsigned long *)0xfe00013c & 0xffffde07;
+	static unsigned long next_warn[7];
+	int idx = 6;
+
+	switch(irq) {
+	case IRQ_PCIPARITY:
+		*(unsigned long *)0xfe000004 = cmd | 1 << 31;
+		idx = 0;
+		err = "parity";
+		break;
+
+	case IRQ_PCITARGETABORT:
+		*(unsigned long *)0xfe000004 = cmd | 1 << 28;
+		idx = 1;
+		err = "target abort";
+		break;
+
+	case IRQ_PCIMASTERABORT:
+		*(unsigned long *)0xfe000004 = cmd | 1 << 29;
+		idx = 2;
+		err = "master abort";
+		break;
+
+	case IRQ_PCIDATAPARITY:
+		*(unsigned long *)0xfe000004 = cmd | 1 << 24;
+		idx = 3;
+		err = "data parity";
+		break;
+
+	case IRQ_DISCARDTIMER:
+		*(unsigned long *)0xfe00013c = ctrl | 1 << 8;
+		idx = 4;
+		err = "discard timer";
+		break;
+
+	case IRQ_SERR:
+		*(unsigned long *)0xfe00013c = ctrl | 1 << 3;
+		idx = 5;
+		err = "system";
+		break;
+	}
+	if (next_warn[idx] <= jiffies) {
+		next_warn[idx] = jiffies + 3 * HZ / 100;
+		printk(KERN_ERR "PCI %s error detected\n", err);
+	}
+}
+
+static struct irqaction irq_pci_error = {
+	irq_pci_err, SA_INTERRUPT, 0, "PCI error", NULL, NULL
+};
+
+__initfunc(void pcibios_init_ebsa285(void))
+{
+	setup_arm_irq(IRQ_PCIPARITY, &irq_pci_error);
+	setup_arm_irq(IRQ_PCITARGETABORT, &irq_pci_error);
+	setup_arm_irq(IRQ_PCIMASTERABORT, &irq_pci_error);
+	setup_arm_irq(IRQ_PCIDATAPARITY, &irq_pci_error);
+	setup_arm_irq(IRQ_DISCARDTIMER, &irq_pci_error);
+	setup_arm_irq(IRQ_SERR, &irq_pci_error);
+
+	/*
+	 * Map our SDRAM at a known address in PCI space, just in case
+	 * the firmware had other ideas.  Using a nonzero base is slightly
+	 * bizarre but apparently necessary to avoid problems with some
+	 * video cards.
+	 *
+	 * We should really only do this if the central function is enabled.
+	 */
+	*(unsigned long *)0xfe000010 = 0;
+	*(unsigned long *)0xfe000018 = 0xe0000000;
+	*(unsigned long *)0xfe0000f8 = 0;
+	*(unsigned long *)0xfe0000fc = 0;
+	*(unsigned long *)0xfe000100 = 0x01fc0000;
+	*(unsigned long *)0xfe000104 = 0;
+	*(unsigned long *)0xfe000108 = 0x80000000;
+	*(unsigned long *)0xfe000004 = 0x17;
+}
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/init_task.c linux/arch/arm/kernel/init_task.c
--- v2.1.131/linux/arch/arm/kernel/init_task.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/init_task.c	Thu Dec 17 09:05:42 1998
@@ -6,7 +6,6 @@
 
 static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
 struct mm_struct init_mm = INIT_MM;
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- v2.1.131/linux/arch/arm/kernel/irq.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/irq.c	Thu Dec 17 09:05:42 1998
@@ -119,7 +119,9 @@
 		*p++ = '\n';
 	}
 
+#ifdef CONFIG_ACORN
 	p += get_fiq_list(p);
+#endif
 	return p - buf;
 }
 
@@ -424,6 +426,8 @@
 	}
 
 	irq_init_irq();
+#ifdef CONFIG_ARCH_ACORN
 	init_FIQ();
+#endif
 	init_dma();
 }
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/setup.c linux/arch/arm/kernel/setup.c
--- v2.1.131/linux/arch/arm/kernel/setup.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/setup.c	Thu Dec 17 09:05:42 1998
@@ -57,13 +57,15 @@
 #endif
 
 #ifndef CONFIG_CMDLINE
-#define CONFIG_CMDLINE	"root=nfs rw console=ttyS1,38400n8"
+#define CONFIG_CMDLINE	"root=/dev/nfs rw"
 #endif
 #define MEM_SIZE	(16*1024*1024)
 #define COMMAND_LINE_SIZE 256
 
 struct drive_info_struct { char dummy[32]; } drive_info;
 struct screen_info screen_info = {
+ orig_video_lines:	30,
+ orig_video_cols:	80,
  orig_video_mode:	0,
  orig_video_ega_bx:	0,
  orig_video_isVGA:	1,
@@ -210,6 +212,8 @@
 
 #ifdef CONFIG_ARCH_ACORN
 	*mem_end_p = GET_MEMORY_END(params);
+#elif defined(CONFIG_ARCH_EBSA285)
+	*mem_end_p = PAGE_OFFSET + params->u1.s.page_size * params->u1.s.nr_pages;
 #else
 	*mem_end_p = PAGE_OFFSET + MEM_SIZE;
 #endif
@@ -305,18 +309,18 @@
 __initfunc(static void
 setup_mem(char *cmd_line, unsigned long *mem_start, unsigned long *mem_end))
 {
-	char c = ' ', *to = command_line;
+	char c, *to = command_line;
 	int len = 0;
 
 	*mem_start = (unsigned long)&_end;
 
 	for (;;) {
-		if (c == ' ' &&
-		    cmd_line[0] == 'm' &&
-		    cmd_line[1] == 'e' &&
-		    cmd_line[2] == 'm' &&
-		    cmd_line[3] == '=') {
-			*mem_end = simple_strtoul(cmd_line+4, &cmd_line, 0);
+		if (cmd_line[0] == ' ' &&
+		    cmd_line[1] == 'm' &&
+		    cmd_line[2] == 'e' &&
+		    cmd_line[3] == 'm' &&
+		    cmd_line[4] == '=') {
+			*mem_end = simple_strtoul(cmd_line+5, &cmd_line, 0);
 			switch(*cmd_line) {
 			case 'M':
 			case 'm':
@@ -336,7 +340,7 @@
 		*to++ = c;
 	}
 
-	*to = '\0';		
+	*to = '\0';
 }
 
 __initfunc(void
@@ -381,33 +385,27 @@
 	conswitchp = &dummy_con;
 #endif
 #endif
-printascii("setup_arch done\n");
 }
 
+static const struct {
+	char *machine_name;
+	char *bus_name;
+} machine_desc[] = {
+	{ "DEC-EBSA110",	"DEC"		},
+	{ "Acorn-RiscPC",	"Acorn"		},
+	{ "Nexus-NexusPCI",	"PCI"		},
+	{ "DEC-EBSA285",	"PCI"		},
+	{ "Corel-Netwinder",	"PCI/ISA"	},
+	{ "Chalice-CATS",	"PCI"		},
+	{ "unknown-TBOX",	"PCI"		}
+};
+
 #if defined(CONFIG_ARCH_ARC)
 #define HARDWARE "Acorn-Archimedes"
 #define IO_BUS	 "Acorn"
 #elif defined(CONFIG_ARCH_A5K)
 #define HARDWARE "Acorn-A5000"
 #define IO_BUS	 "Acorn"
-#elif defined(CONFIG_ARCH_RPC)
-#define HARDWARE "Acorn-RiscPC"
-#define IO_BUS	 "Acorn"
-#elif defined(CONFIG_ARCH_EBSA110)
-#define HARDWARE "DEC-EBSA110"
-#define IO_BUS	 "DEC"
-#elif defined(CONFIG_ARCH_EBSA285)
-#define HARDWARE "DEC-EBSA285"
-#define IO_BUS   "PCI"
-#elif defined(CONFIG_ARCH_NEXUSPCI)
-#define HARDWARE "Nexus-NexusPCI"
-#define IO_BUS   "PCI"
-#elif defined(CONFIG_ARCH_VNC)
-#define HARDWARE "Corel-VNC"
-#define IO_BUS   "PCI"
-#else
-#define HARDWARE "unknown"
-#define IO_BUS   "unknown"
 #endif
 
 #if defined(CONFIG_CPU_ARM2)
@@ -439,8 +437,17 @@
 		(int)processor_id & 15,
 		(loops_per_sec+2500) / 500000,
 		((loops_per_sec+2500) / 5000) % 100,
+#ifdef HARDWARE
 		HARDWARE,
+#else
+		machine_desc[machine_type].machine_name,
+#endif
 		OPTIMISATION,
-		IO_BUS);
+#ifdef IO_BUS
+		IO_BUS
+#else
+		machine_desc[machine_type].bus_name
+#endif
+		);
 	return len;
 }
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.1.131/linux/arch/arm/kernel/sys_arm.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/sys_arm.c	Thu Dec 17 09:05:42 1998
@@ -77,7 +77,8 @@
 		goto out;
 	if (!(a.flags & MAP_ANONYMOUS)) {
 		error = -EBADF;
-		if (a.fd >= NR_OPEN || !(file = current->files->fd[a.fd]))
+		if (a.fd >= current->files->max_fds || 
+		    !(file = current->files->fd[a.fd]))
 			goto out;
 	}
 	a.flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
diff -u --recursive --new-file v2.1.131/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.1.131/linux/arch/arm/kernel/traps.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/traps.c	Thu Dec 17 09:05:42 1998
@@ -51,7 +51,7 @@
 	if (stackptr < 0x02048000 || stackptr + size > 0x03000000)
         	return -EFAULT;
 #else
-	if (stackptr < 0xc0000000 || stackptr + size > (unsigned long)high_memory)
+	if (stackptr < PAGE_OFFSET || stackptr + size > (unsigned long)high_memory)
 		return -EFAULT;
 #endif
 		return 0;
@@ -175,7 +175,7 @@
 		printk("(sp underflow)");
 	printk("\n");
 
-	dump_mem(cstack, sstack + 4096);
+	dump_mem(cstack - 16, sstack + 4096);
 
 	frameptr = regs->ARM_fp;
 	if (frameptr) {
diff -u --recursive --new-file v2.1.131/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.1.131/linux/arch/arm/lib/Makefile	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/lib/Makefile	Thu Dec 17 09:05:42 1998
@@ -26,6 +26,10 @@
   L_OBJS += io-ebsa110.o
 endif
 
+ifeq ($(MACHINE),vnc)
+  L_OBJS += io-ebsa285.o
+endif
+
 ifeq ($(MACHINE),ebsa285)
   L_OBJS += io-ebsa285.o
 endif
diff -u --recursive --new-file v2.1.131/linux/arch/arm/lib/io-ebsa285.S linux/arch/arm/lib/io-ebsa285.S
--- v2.1.131/linux/arch/arm/lib/io-ebsa285.S	Tue Jul 21 00:15:30 1998
+++ linux/arch/arm/lib/io-ebsa285.S	Thu Dec 17 09:05:42 1998
@@ -104,24 +104,75 @@
 ENTRY(outsw)
 		add	r0, r0, #0xff000000
 		add	r0, r0, #0x00e00000
-1:		teq	r2, #0
-		ldrneh	r3, [r1], #2
-		strneh	r3, [r0]
-		subne	r2, r2, #1
-		bne	1b
+1:		subs	r2, r2, #1
+		ldrgeh	r3, [r1], #2
+		strgeh	r3, [r0]
+		bgt	1b
 		mov	pc, lr
 
 ENTRY(inswb)
 		mov	r2, r2, lsr #1
 ENTRY(insw)
+		stmfd	sp!, {r4, r5, lr}
 		add	r0, r0, #0xff000000
 		add	r0, r0, #0x00e00000
-1:		teq	r2, #0
+						@ + 8 + 9 +10 +11 +12 +13 +14 +15 +16 +17
+		subs	ip, r2, #8
+		blo	too_little
+						@ + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
+		ands	lr, r1, #3		@ check alignment
+		beq	1f
+
+		ldrh	r3, [r0]
+		strh	r3, [r1], #2
+		sub	ip, ip, #1
+		cmn	ip, #8
+		blo	too_little
+
+1:		ldrh	r2, [r0]
+		ldrh	r3, [r0]
+		orr	r2, r2, r3, lsl #16
+		ldrh	r3, [r0]
+		ldrh	r4, [r0]
+		orr	r3, r3, r4, lsl #16
+		ldrh	r4, [r0]
+		ldrh	r5, [r0]
+		orr	r4, r4, r5, lsl #16
+		ldrh	r5, [r0]
+		ldrh	lr, [r0]
+		orr	r5, r5, lr, lsl #16
+		stmia	r1!, {r2, r3, r4, r5}
+		subs	ip, ip, #8
+						@ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 + 0 + 1
+		bhs	1b
+						@ - 8 - 7 - 6 - 5 - 4 - 3 - 2 - 1 - 8 - 7
+		cmn	ip, #4
+		ldrhsh	r2, [r0]		@ ... ... ... ... - 4 - 3 - 2 - 1 ... ...
+		ldrhsh	r3, [r0]
+		orrhs	r2, r2, r3, lsl #16
+		ldrhsh	r3, [r0]
+		ldrhsh	r4, [r0]
+		orrhs	r3, r3, r4, lsl #16
+		stmhsia	r1!, {r2, r3}
+
+		tst	ip, #2
+		ldrneh	r2, [r0]		@ ... ... - 6 - 5 ... ... - 2 - 1 ... ...
 		ldrneh	r3, [r0]
-		strneh	r3, [r1], #2
-		subne	r2, r2, #1
-		bne	1b
-		mov	pc, lr
+		orrne	r2, r2, r3, lsl #16
+		strne	r2, [r1], #4
+
+		tst	ip, #1
+		ldrneh	r2, [r0]
+		strneh	r2, [r1], #2
+
+		ldmfd	sp!, {r4, r5, pc}
+
+too_little:	subs	r2, r2, #1
+		ldrgeh	r3, [r0]
+		strgeh	r3, [r1], #2
+		bgt	too_little
+
+		ldmfd	sp!, {r4, r5, pc}
 
 
 ENTRY(insb)
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/fault-armo.c linux/arch/arm/mm/fault-armo.c
--- v2.1.131/linux/arch/arm/mm/fault-armo.c	Wed Sep  9 14:51:05 1998
+++ linux/arch/arm/mm/fault-armo.c	Thu Dec 17 09:05:42 1998
@@ -174,7 +174,7 @@
 	}
 
 	/* Are we prepared to handle this kernel fault?  */
-	if ((fixup = search_exception_table(regs->ARM_pc)) != 0) {
+	if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
 		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
 			tsk->comm, regs->ARM_pc, addr, fixup);
 		regs->ARM_pc = fixup;
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.1.131/linux/arch/arm/mm/fault-armv.c	Wed Sep  9 14:51:05 1998
+++ linux/arch/arm/mm/fault-armv.c	Thu Dec 17 09:05:42 1998
@@ -208,7 +208,7 @@
 	}
 
 	/* Are we prepared to handle this kernel fault?  */
-	if ((fixup = search_exception_table(regs->ARM_pc)) != 0) {
+	if ((fixup = search_exception_table(instruction_pointer(regs))) != 0) {
 		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
 			tsk->comm, regs->ARM_pc, addr, fixup);
 		regs->ARM_pc = fixup;
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.1.131/linux/arch/arm/mm/init.c	Wed Sep  9 14:51:05 1998
+++ linux/arch/arm/mm/init.c	Thu Dec 17 09:05:42 1998
@@ -192,6 +192,15 @@
 		 reservedpages << (PAGE_SHIFT-10),
 		 datapages << (PAGE_SHIFT-10),
 		 initpages << (PAGE_SHIFT-10));
+
+#ifdef CONFIG_CPU_26
+	if (max_mapnr <= 128) {
+		extern int sysctl_overcommit_memory;
+		/* On a machine this small we won't get anywhere without
+		   overcommit, so turn it on by default.  */
+		sysctl_overcommit_memory = 1;
+	}
+#endif
 }
 
 void free_initmem (void)
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/mm-ebsa285.c linux/arch/arm/mm/mm-ebsa285.c
--- v2.1.131/linux/arch/arm/mm/mm-ebsa285.c	Tue Jul 21 00:15:30 1998
+++ linux/arch/arm/mm/mm-ebsa285.c	Thu Dec 17 09:05:42 1998
@@ -5,7 +5,6 @@
  *
  * Copyright (C) 1998 Russell King, Dave Gilbert.
  */
-#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/init.h>
@@ -14,46 +13,7 @@
 #include <asm/page.h>
 #include <asm/io.h>
 #include <asm/proc/mm-init.h>
-
-/*
- * These two functions convert PCI bus addresses to virtual addresses
- * and back again.
- */ 
-unsigned long __virt_to_bus(unsigned long res)
-{
-	if (res < PAGE_OFFSET || res >= 0xD0000000) {
-		printk("__virt_to_bus: invalid address 0x%08lx\n", res);
-#ifdef CONFIG_DEBUG_ERRORS
-		__backtrace();
-#endif
-	} else
-		res = (res - PAGE_OFFSET) + 0x10000000;
-
-	return res;
-}
-
-unsigned long __bus_to_virt(unsigned long res)
-{
-	if (res < 0x10000000 || res >= 0x20000000) {
-		printk("__bus_to_virt: invalid address 0x%08lx\n", res);
-#ifdef CONFIG_DEBUG_ERRORS
-		__backtrace();
-#endif
-	} else
-		res = (res - 0x10000000) + PAGE_OFFSET;
-
-	return res;
-}
-
-/*    Logical    Physical
- * 0xfff00000	0x40000000	X-Bus
- * 0xffe00000	0x7c000000	PCI I/O space
- * 0xfe000000	0x42000000	CSR
- * 0xfd000000	0x78000000	Outbound write flush
- * 0xfc000000	0x79000000	PCI IACK/special space
- * 0xf9000000	0x7a000000	PCI Config type 1
- * 0xf8000000	0x7b000000	PCI Config type 0
- */
+#include <asm/dec21285.h>
 
 /*
  * This is to allow us to fiddle with the EEPROM
@@ -65,15 +25,15 @@
  *  until we're happy with them...
  */
 #define MAPPING \
-	{ 0xd8000000, 0x41000000, 0x00400000, DOMAIN_USER, 1, 1 },	/* EEPROM */	    \
-	{ 0xdc000000, 0x7c000000, 0x00100000, DOMAIN_USER, 1, 1 },	/* VGA */	    \
-	{ 0xe0000000, 0x80000000, 0x10000000, DOMAIN_USER, 1, 1 },	/* VGA */	    \
-	{ 0xf8000000, 0x7b000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 0 Config */ \
-	{ 0xf9000000, 0x7a000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 1 Config */ \
-	{ 0xfc000000, 0x79000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* PCI IACK	 */ \
-	{ 0xfd000000, 0x78000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Outbound wflsh*/ \
-	{ 0xfe000000, 0x42000000, 0x01000000, DOMAIN_IO  , 0, 1 },	/* CSR		 */ \
-	{ 0xffe00000, 0x7c000000, 0x00100000, DOMAIN_IO  , 0, 1 },	/* PCI I/O	 */ \
-	{ 0xfff00000, 0x40000000, 0x00100000, DOMAIN_IO  , 0, 1 },	/* X-Bus	 */
+  { 0xd8000000, DC21285_FLASH,		      0x00400000, DOMAIN_USER, 1, 1 },	/* EEPROM */	    \
+  { 0xdc000000, 0x7c000000,		      0x00100000, DOMAIN_USER, 1, 1 },	/* VGA */	    \
+  { 0xe0000000, DC21285_PCI_MEM,	      0x18000000, DOMAIN_USER, 1, 1 },	/* VGA */	    \
+  { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG,    0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 0 Config */ \
+  { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG,    0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 1 Config */ \
+  { PCI_IACK,	DC21285_PCI_IACK,	      0x01000000, DOMAIN_IO  , 0, 1 },	/* PCI IACK	 */ \
+  { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Out wrflsh	 */ \
+  { 0xfe000000, DC21285_ARMCSR_BASE,	      0x01000000, DOMAIN_IO  , 0, 1 },	/* CSR		 */ \
+  { 0xffe00000, DC21285_PCI_IO, 	      0x00100000, DOMAIN_IO  , 0, 1 },	/* PCI I/O	 */ \
+  { 0xfff00000, 0x40000000,		      0x00100000, DOMAIN_IO  , 0, 1 },	/* X-Bus	 */
 
 #include "mm-armv.c"
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/mm-rpc.c linux/arch/arm/mm/mm-rpc.c
--- v2.1.131/linux/arch/arm/mm/mm-rpc.c	Wed Sep  9 14:51:05 1998
+++ linux/arch/arm/mm/mm-rpc.c	Thu Dec 17 09:05:42 1998
@@ -91,7 +91,8 @@
 
 #define MAPPING \
 	{ SCREEN2_BASE,	SCREEN_START,	2*1048576, DOMAIN_IO, 0, 1 },	/* VRAM		*/ \
-	{ IO_BASE,	IO_START,	IO_SIZE	 , DOMAIN_IO, 0, 1 }	/* IO space	*/
+	{ IO_BASE,	IO_START,	IO_SIZE	 , DOMAIN_IO, 0, 1 },	/* IO space	*/ \
+	{ EASI_BASE,	EASI_START,	EASI_SIZE, DOMAIN_IO, 0, 1 }	/* EASI space	*/
 /*
  * Include common routine to set up page tables
  */
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/mm-vnc.c linux/arch/arm/mm/mm-vnc.c
--- v2.1.131/linux/arch/arm/mm/mm-vnc.c	Tue Jul 21 00:15:30 1998
+++ linux/arch/arm/mm/mm-vnc.c	Thu Dec 17 09:05:42 1998
@@ -13,20 +13,19 @@
 #include <asm/page.h>
 #include <asm/io.h>
 #include <asm/proc/mm-init.h>
+#include <asm/dec21285.h>
 
 /* Table describing the MMU translation mapping
  * mainly used to set up the I/O mappings.
  */ 
 #define MAPPING \
-  { 0xe0000000, DC21285_PCI_IO,		      0x00100000, DOMAIN_IO, 0, 1 }, /* PCI I/O		*/ \
-  { 0xe0100000, DC21285_PCI_TYPE_0_CONFIG,    0x00f00000, DOMAIN_IO, 0, 1 }, /* Type 0 Config	*/ \
-  { 0xe1000000, DC21285_ARMCSR_BASE,	      0x00100000, DOMAIN_IO, 0, 1 }, /* ARM CSR		*/ \
-  { 0xe1100000, DC21285_PCI_IACK,	      0x00100000, DOMAIN_IO, 0, 1 }, /* PCI IACK	*/ \
-  { 0xe1300000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
-  { 0xe1400000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
-  { 0xe1500000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
-  { 0xe1600000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
-  { 0xe1700000, DC21285_OUTBOUND_WRITE_FLUSH, 0x00100000, DOMAIN_IO, 0, 1 }, /* Out wrflsh	*/ \
-  { 0xe1800000, DC21285_FLASH,                0x00800000, DOMAIN_IO, 0, 1 }  /* Flash		*/
+  { 0xd0000000, DC21285_FLASH,		      0x00800000, DOMAIN_IO  , 0, 1 },	/* Flash	 */ \
+  { 0xe0000000, DC21285_PCI_MEM,	      0x18000000, DOMAIN_IO  , 0, 1 },	/* PCI Mem 	 */ \
+  { 0xf8000000, DC21285_PCI_TYPE_0_CONFIG,    0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 0 Config */ \
+  { 0xf9000000, DC21285_PCI_TYPE_1_CONFIG,    0x01000000, DOMAIN_IO  , 0, 1 },	/* Type 1 Config */ \
+  { PCI_IACK,	DC21285_PCI_IACK,	      0x01000000, DOMAIN_IO  , 0, 1 },	/* PCI IACK	 */ \
+  { 0xfd000000, DC21285_OUTBOUND_WRITE_FLUSH, 0x01000000, DOMAIN_IO  , 0, 1 },	/* Out wrflsh	 */ \
+  { 0xfe000000, DC21285_ARMCSR_BASE,	      0x01000000, DOMAIN_IO  , 0, 1 },	/* CSR		 */ \
+  { 0xffe00000, DC21285_PCI_IO, 	      0x00100000, DOMAIN_IO  , 0, 1 },	/* PCI I/O	 */ \
 
 #include "mm-armv.c"
diff -u --recursive --new-file v2.1.131/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.1.131/linux/arch/arm/mm/proc-sa110.S	Wed Sep  9 14:51:05 1998
+++ linux/arch/arm/mm/proc-sa110.S	Thu Dec 17 09:05:42 1998
@@ -10,6 +10,11 @@
 #include <asm/assembler.h>
 #include "../lib/constants.h"
 
+/* This is the maximum size of an area which will be flushed.  If the area
+ * is larger than this, then we flush the whole cache
+ */
+#define MAX_AREA_SIZE	32768
+
 		.data
 Lclean_switch:	.long	0
 		.text
@@ -52,7 +57,7 @@
 		.align	5
 _sa110_flush_cache_area:
 		sub	r3, r1, r0
-		cmp	r3, #32768
+		cmp	r3, #MAX_AREA_SIZE
 		bgt	_sa110_flush_cache_all_r2
 1:		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		mcr	p15, 0, r0, c7, c6, 1		@ flush D entry
@@ -79,16 +84,17 @@
 		.align	5
 _sa110_cache_wback_area:
 		sub	r3, r1, r0
-		cmp	r3, #32768
-		movgt	r2, #0
-		bgt	_sa110_flush_cache_all
+		cmp	r3, #MAX_AREA_SIZE
+		mov	r2, #0
+		bgt	_sa110_flush_cache_all_r2
+		bic	r0, r0, #31
 1:		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		add	r0, r0, #32
 		mcr	p15, 0, r0, c7, c10, 1		@ clean D entry
 		add	r0, r0, #32
 		cmp	r0, r1
 		blt	1b
-		mcr	p15, 0, r0, c7, c10, 4		@ drain WB
+		mcr	p15, 0, r2, c7, c10, 4		@ drain WB
 		mov	pc, lr
 
 /*
diff -u --recursive --new-file v2.1.131/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.1.131/linux/arch/i386/config.in	Wed Dec 16 10:32:54 1998
+++ linux/arch/i386/config.in	Fri Dec 18 14:01:48 1998
@@ -20,6 +20,7 @@
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
 fi
+bool 'Symmetric multi-processing support' CONFIG_SMP
 endmenu
 
 mainmenu_option next_comment
@@ -39,6 +40,9 @@
 if [ "$CONFIG_PCI" = "y" ]; then
   bool '   PCI BIOS support' CONFIG_PCI_BIOS
   bool '   PCI direct access support' CONFIG_PCI_DIRECT
+  if [ "$CONFIG_PCI_BIOS" = "n" -a "$CONFIG_PCI_DIRECT" = "n" ]; then
+    define_bool CONFIG_PCI_BIOS "y"
+  fi
   bool '   PCI quirks' CONFIG_PCI_QUIRKS
   if [ "$CONFIG_PCI_QUIRKS" = "y" -a "$CONFIG_EXPERIMENTAL" = "y" ]; then
     bool '   PCI bridge optimization (experimental)' CONFIG_PCI_OPTIMIZE
@@ -108,12 +112,15 @@
 
 source net/ax25/Config.in
 
+source net/irda/Config.in
+
 mainmenu_option next_comment
 comment 'ISDN subsystem'
-
-tristate 'ISDN support' CONFIG_ISDN
-if [ "$CONFIG_ISDN" != "n" ]; then
-  source drivers/isdn/Config.in
+if [ "$CONFIG_NET" != "n" ]; then
+  tristate 'ISDN support' CONFIG_ISDN
+  if [ "$CONFIG_ISDN" != "n" ]; then
+    source drivers/isdn/Config.in
+  fi
 fi
 endmenu
 
diff -u --recursive --new-file v2.1.131/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.1.131/linux/arch/i386/defconfig	Thu Nov 19 09:56:27 1998
+++ linux/arch/i386/defconfig	Fri Dec 18 14:06:01 1998
@@ -15,6 +15,7 @@
 CONFIG_M586=y
 # CONFIG_M686 is not set
 # CONFIG_MATH_EMULATION is not set
+CONFIG_SMP=y
 
 #
 # Loadable module support
@@ -139,6 +140,7 @@
 # SCSI low-level drivers
 #
 # CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_ACARD is not set
 # CONFIG_SCSI_AHA152X is not set
 # CONFIG_SCSI_AHA1542 is not set
 # CONFIG_SCSI_AHA1740 is not set
@@ -146,14 +148,16 @@
 # CONFIG_SCSI_ADVANSYS is not set
 # CONFIG_SCSI_IN2000 is not set
 # CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_MEGARAID is not set
 # CONFIG_SCSI_BUSLOGIC is not set
 # CONFIG_SCSI_DTC3280 is not set
+# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_EATA_DMA is not set
 # CONFIG_SCSI_EATA_PIO is not set
-# CONFIG_SCSI_EATA is not set
 # CONFIG_SCSI_FUTURE_DOMAIN is not set
 # CONFIG_SCSI_GDTH is not set
 # CONFIG_SCSI_GENERIC_NCR5380 is not set
+# CONFIG_SCSI_INITIO is not set
 # CONFIG_SCSI_NCR53C406A is not set
 # CONFIG_SCSI_NCR53C7xx is not set
 CONFIG_SCSI_NCR53C8XX=y
@@ -168,6 +172,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
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.1.131/linux/arch/i386/kernel/Makefile	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/Makefile	Fri Dec 18 14:01:48 1998
@@ -38,7 +38,7 @@
 OX_OBJS += apm.o
 endif
 
-ifdef SMP
+ifdef CONFIG_SMP
 O_OBJS += io_apic.o smp.o trampoline.o
 endif
 
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.1.131/linux/arch/i386/kernel/entry.S	Wed Dec 16 10:32:54 1998
+++ linux/arch/i386/kernel/entry.S	Wed Dec 16 11:08:23 1998
@@ -155,7 +155,7 @@
 ret_from_fork:
 	GET_CURRENT(%ebx)
 #ifdef __SMP__
-	btrl	$0, SYMBOL_NAME(scheduler_lock)
+	lock ; btrl $0, SYMBOL_NAME(scheduler_lock)
 #endif /* __SMP__ */
 	jmp	ret_from_sys_call
 
@@ -193,6 +193,7 @@
 
 	ALIGN
 signal_return:
+	sti				# we can get here from an interrupt handler
 	testl $(VM_MASK),EFLAGS(%esp)
 	movl %esp,%eax
 	jne v86_signal_return
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.1.131/linux/arch/i386/kernel/io_apic.c	Fri Oct  9 13:27:05 1998
+++ linux/arch/i386/kernel/io_apic.c	Fri Dec 18 09:33:39 1998
@@ -225,6 +225,13 @@
 int pirq_entries [MAX_PIRQS];
 int pirqs_enabled;
 
+void __init ioapic_setup(char *str, int *ints)
+{
+	extern int skip_ioapic_setup;	/* defined in arch/i386/kernel/smp.c */
+
+	skip_ioapic_setup = 1;
+}
+
 void __init ioapic_pirq_setup(char *str, int *ints)
 {
 	int i, max;
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.1.131/linux/arch/i386/kernel/irq.c	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/irq.c	Fri Dec 18 08:22:56 1998
@@ -335,16 +335,17 @@
 	int i;
 	unsigned long *stack;
 	int cpu = smp_processor_id();
+	extern char *get_options(char *str, int *ints);
 
 	printk("\n%s, CPU %d:\n", str, cpu);
 	printk("irq:  %d [%d %d]\n",
 		atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
 	printk("bh:   %d [%d %d]\n",
 		atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
-	stack = (unsigned long *) &str;
+	stack = (unsigned long *) &stack;
 	for (i = 40; i ; i--) {
 		unsigned long x = *++stack;
-		if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
+		if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) {
 			printk("<[%08lx]> ", x);
 		}
 	}
@@ -691,8 +692,10 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&irq_controller_lock, flags);
-	irq_desc[irq].status |= IRQ_DISABLED;
-	irq_desc[irq].handler->disable(irq);
+	if (!irq_desc[irq].depth++) {
+		irq_desc[irq].status |= IRQ_DISABLED;
+		irq_desc[irq].handler->disable(irq);
+	}
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
 
 	if (irq_desc[irq].status & IRQ_INPROGRESS)
@@ -704,16 +707,18 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&irq_controller_lock, flags);
-	/*
-	 * In contrast to the above, we should _not_ have any concurrent
-	 * interrupt activity here, so we just clear both disabled bits.
-	 *
-	 * This allows us to have IRQ_INPROGRESS set until we actually
-	 * install a handler for this interrupt (make irq autodetection
-	 * work by just looking at the status field for the irq)
-	 */
-	irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS);
-	irq_desc[irq].handler->enable(irq);
+	switch (irq_desc[irq].depth) {
+	case 1:
+		irq_desc[irq].status &= ~IRQ_DISABLED;
+		irq_desc[irq].handler->enable(irq);
+		/* fall throught */
+	default:
+		irq_desc[irq].depth--;
+		break;
+	case 0:
+		printk("enable_irq() unbalanced from %p\n",
+		       __builtin_return_address(0));
+	}
 	spin_unlock_irqrestore(&irq_controller_lock, flags);
 }
 
@@ -798,6 +803,7 @@
 	*p = new;
 
 	if (!shared) {
+		irq_desc[irq].depth = 0;
 		irq_desc[irq].status &= ~(IRQ_DISABLED | IRQ_INPROGRESS);
 		irq_desc[irq].handler->startup(irq);
 	}
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.1.131/linux/arch/i386/kernel/irq.h	Thu Sep 17 17:53:34 1998
+++ linux/arch/i386/kernel/irq.h	Tue Dec 22 10:50:45 1998
@@ -37,7 +37,7 @@
 	unsigned int status;			/* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
 	struct hw_interrupt_type *handler;	/* handle/enable/disable functions */
 	struct irqaction *action;		/* IRQ action list */
-	unsigned int unused[3];
+	unsigned int depth;			/* Disable depth for nested irq disables */
 } irq_desc_t;
 
 #define IRQ0_TRAP_VECTOR 0x51
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.1.131/linux/arch/i386/kernel/process.c	Wed Dec 16 10:32:54 1998
+++ linux/arch/i386/kernel/process.c	Wed Dec 16 12:38:45 1998
@@ -105,19 +105,24 @@
  */ 
 static int cpu_idle(void *unused)
 {
-	unsigned long start_idle = jiffies;
+	int work = 1;
+	unsigned long start_idle = 0;
 
 	/* endless idle loop with no priority at all */
+	current->priority = 0;
+	current->counter = -100;
 	for (;;) {
+		if (work)
+			start_idle = jiffies;
+
 		if (jiffies - start_idle > HARD_IDLE_TIMEOUT) 
 			hard_idle();
 		else  {
 			if (boot_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
 		        	__asm__("hlt");
 		}
-		if (current->need_resched) 
-			start_idle = jiffies;
-		current->policy = SCHED_YIELD;
+
+		work = current->need_resched;
 		schedule();
 		check_pgt_cache();
 	}
@@ -131,12 +136,12 @@
 
 int cpu_idle(void *unused)
 {
-
 	/* endless idle loop with no priority at all */
+	current->priority = 0;
+	current->counter = -100;
 	while(1) {
 		if (current_cpu_data.hlt_works_ok && !hlt_counter && !current->need_resched)
 			__asm__("hlt");
-		current->policy = SCHED_YIELD;
 		schedule();
 		check_pgt_cache();
 	}
@@ -579,7 +584,6 @@
 	*childregs = *regs;
 	childregs->eax = 0;
 	childregs->esp = esp;
-	childregs->eflags = regs->eflags & 0xffffcfff;  /* iopl always 0 for a new process */	
 
 	p->tss.esp = (unsigned long) childregs;
 	p->tss.esp0 = (unsigned long) (childregs+1);
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.1.131/linux/arch/i386/kernel/smp.c	Fri Oct  9 13:27:05 1998
+++ linux/arch/i386/kernel/smp.c	Mon Dec 21 12:43:41 1998
@@ -29,23 +29,17 @@
  */
 
 #include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/timer.h>
-#include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/kernel_stat.h>
 #include <linux/delay.h>
 #include <linux/mc146818rtc.h>
 #include <asm/i82489.h>
-#include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <asm/pgtable.h>
 #include <asm/bitops.h>
 #include <asm/pgtable.h>
-#include <asm/smp.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_MTRR
@@ -159,6 +153,7 @@
 int mp_bus_id_to_pci_bus [MAX_MP_BUSSES] = { -1, };
 int mp_current_pci_id = 0;
 unsigned long mp_lapic_addr = 0;
+int skip_ioapic_setup = 0;				/* 1 if "noapic" boot option passed */
 
 /* #define SMP_DEBUG */
 
@@ -405,7 +400,11 @@
 		}
 	}
 	if (ioapics > 1)
+	{
 		printk("Warning: Multiple IO-APICs not yet supported.\n");
+		printk("Warning: switching to non APIC mode.\n");
+		skip_ioapic_setup=1;
+	}
 	return num_processors;
 }
 
@@ -1170,11 +1169,11 @@
 	 * Here we can be sure that there is an IO-APIC in the system. Let's
 	 * go and set it up:
 	 */
-	setup_IO_APIC();
+	if (!skip_ioapic_setup) 
+		setup_IO_APIC();
 
 smp_done:
 }
-
 
 void send_IPI(int dest, int vector)
 {
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/sys_i386.c linux/arch/i386/kernel/sys_i386.c
--- v2.1.131/linux/arch/i386/kernel/sys_i386.c	Wed Jun 24 22:54:03 1998
+++ linux/arch/i386/kernel/sys_i386.c	Thu Dec 17 16:27:35 1998
@@ -108,108 +108,94 @@
  *
  * This is really horribly ugly.
  */
-asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
+asmlinkage int sys_ipc (uint call, int first, int second,
+			int third, void *ptr, long fifth)
 {
 	int version, ret;
 
-	lock_kernel();
 	version = call >> 16; /* hack for backward compatibility */
 	call &= 0xffff;
 
 	if (call <= SEMCTL)
 		switch (call) {
 		case SEMOP:
-			ret = sys_semop (first, (struct sembuf *)ptr, second);
-			goto out;
+			return sys_semop (first, (struct sembuf *)ptr, second);
 		case SEMGET:
-			ret = sys_semget (first, second, third);
-			goto out;
+			return sys_semget (first, second, third);
 		case SEMCTL: {
 			union semun fourth;
-			ret = -EINVAL;
 			if (!ptr)
-				goto out;
-			ret = -EFAULT;
+				return -EINVAL;
 			if (get_user(fourth.__pad, (void **) ptr))
-				goto out;	
-			ret = sys_semctl (first, second, third, fourth);
-			goto out;
+				return -EFAULT;
+			return sys_semctl (first, second, third, fourth);
 			}
 		default:
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
+
 	if (call <= MSGCTL) 
 		switch (call) {
 		case MSGSND:
-			ret = sys_msgsnd (first, (struct msgbuf *) ptr, 
+			return sys_msgsnd (first, (struct msgbuf *) ptr, 
 					  second, third);
-			goto out;
 		case MSGRCV:
 			switch (version) {
 			case 0: {
 				struct ipc_kludge tmp;
-				ret = -EINVAL;
 				if (!ptr)
-					goto out;
-				ret = -EFAULT;
-				if (copy_from_user(&tmp,(struct ipc_kludge *) ptr, 
-								   sizeof (tmp)))
-					goto out; 	
-				ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
-				goto out;
+					return -EINVAL;
+				
+				if (copy_from_user(&tmp,
+						   (struct ipc_kludge *) ptr, 
+						   sizeof (tmp)))
+					return -EFAULT;
+				return sys_msgrcv (first, tmp.msgp, second,
+						   tmp.msgtyp, third);
 				}
-			case 1: default:
-				ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
-				goto out;
+			default:
+				return sys_msgrcv (first,
+						   (struct msgbuf *) ptr,
+						   second, fifth, third);
 			}
 		case MSGGET:
-			ret = sys_msgget ((key_t) first, second);
-			goto out;
+			return sys_msgget ((key_t) first, second);
 		case MSGCTL:
-			ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
-			goto out;
+			return sys_msgctl (first, second,
+					   (struct msqid_ds *) ptr);
 		default:
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 	if (call <= SHMCTL) 
 		switch (call) {
 		case SHMAT:
 			switch (version) {
-			case 0: default: {
+			default: {
 				ulong raddr;
-				ret = sys_shmat (first, (char *) ptr, second, &raddr);
+				ret = sys_shmat (first, (char *) ptr,
+						 second, &raddr);
 				if (ret)
-					goto out;
-				ret = put_user (raddr, (ulong *) third);
-				goto out;
+					return ret;
+				return put_user (raddr, (ulong *) third);
 			}
 			case 1:	/* iBCS2 emulator entry point */
-				ret = -EINVAL;
 				if (!segment_eq(get_fs(), get_ds()))
-					goto out;
-				ret = sys_shmat (first, (char *) ptr, second, (ulong *) third);
-				goto out;
+					return -EINVAL;
+				return sys_shmat (first, (char *) ptr,
+						  second, (ulong *) third);
 			}
 		case SHMDT: 
-			ret = sys_shmdt ((char *)ptr);
-			goto out;
+			return sys_shmdt ((char *)ptr);
 		case SHMGET:
-			ret = sys_shmget (first, second, third);
-			goto out;
+			return sys_shmget (first, second, third);
 		case SHMCTL:
-			ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
-			goto out;
+			return sys_shmctl (first, second,
+					   (struct shmid_ds *) ptr);
 		default:
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
-	else
-		ret = -EINVAL;
-out:
-	unlock_kernel();
-	return ret;
+	
+	return -EINVAL;
 }
 
 /*
diff -u --recursive --new-file v2.1.131/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.1.131/linux/arch/i386/kernel/time.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/i386/kernel/time.c	Fri Dec 18 08:22:56 1998
@@ -20,6 +20,10 @@
  *	(C. Scott Ananian <cananian@alumni.princeton.edu>, Andrew D.
  *	Balsa <andrebalsa@altern.org>, Philip Gladstone <philip@raptor.com>;
  *	ported from 2.0.35 Jumbo-9 by Michael Krause <m.krause@tu-harburg.de>).
+ * 1998-12-16    Andrea Arcangeli
+ *	Fixed Jumbo-9 code in 2.1.131: do_gettimeofday was missing 1 jiffy
+ *	because was not accounting lost_ticks. I also removed some ugly
+ *	not needed global cli() and where needed I used a disable_irq(0).
  */
 
 /* What about the "updated NTP code" stuff in 2.0 time.c? It's not in
@@ -92,9 +96,9 @@
 	eax -= last_tsc_low;	/* tsc_low delta */
 
 	/*
-         * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient.
-         *             = (tsc_low delta) / (clocks_per_usec)
-         *             = (tsc_low delta) / (clocks_per_jiffy / usecs_per_jiffy)
+         * Time offset = (tsc_low delta) * fast_gettimeoffset_quotient
+         *             = (tsc_low delta) * (usecs_per_clock)
+         *             = (tsc_low delta) * (usecs_per_jiffy / clocks_per_jiffy)
 	 *
 	 * Using a mull instead of a divl saves up to 31 clock cycles
 	 * in the critical path.
@@ -230,17 +234,19 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
+	extern volatile unsigned long lost_ticks;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	save_flags(flags); cli();
 	*tv = xtime;
 	tv->tv_usec += do_gettimeoffset();
-	if (tv->tv_usec >= 1000000) {
+	if (lost_ticks)
+		tv->tv_usec += lost_ticks * (1000000/HZ);
+	restore_flags(flags);
+	while (tv->tv_usec >= 1000000) {
 		tv->tv_usec -= 1000000;
 		tv->tv_sec++;
 	}
-	restore_flags(flags);
 }
 
 void do_settimeofday(struct timeval *tv)
@@ -254,7 +260,7 @@
 	 */
 	tv->tv_usec -= do_gettimeoffset();
 
-	if (tv->tv_usec < 0) {
+	while (tv->tv_usec < 0) {
 		tv->tv_usec += 1000000;
 		tv->tv_sec--;
 	}
@@ -399,18 +405,20 @@
  */
 static void pentium_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-	int count, flags;
+	int count;
 
 	/* It is important that these two operations happen almost at the
 	 * same time. We do the RDTSC stuff first, since it's faster. To
-         * avoid any inconsistencies, we disable interrupts locally.
+         * avoid any inconsistencies, we need interrupts disabled locally.
          */
+
+	/*
+	 * Interrupts are just disabled locally since the timer irq has the
+	 * SA_INTERRUPT flag set. -arca
+	 */
 	
-	__save_flags(flags);
-	__cli(); 
 	/* read Pentium cycle counter */
-	__asm__("rdtsc"
-		:"=a" (last_tsc_low):: "eax", "edx");
+	__asm__("rdtsc" : "=a" (last_tsc_low) : : "edx");
 
 	outb_p(0x00, 0x43);     /* latch the count ASAP */
 
@@ -419,8 +427,7 @@
 
 	count = ((LATCH-1) - count) * TICK_SIZE;
 	delay_at_last_interrupt = (count + LATCH/2) / LATCH;
-	__restore_flags(flags);
-       
+ 
 	timer_interrupt(irq, NULL, regs);
 }
 
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.1.131/linux/arch/m68k/Makefile	Tue Jun 23 10:01:20 1998
+++ linux/arch/m68k/Makefile	Thu Dec 17 09:06:25 1998
@@ -116,6 +116,7 @@
 
 archclean:
 	rm -f vmlinux.gz
+	rm -f kernel/m68k_defs.h kernel/m68k_defs.d
 
 archmrproper:
 
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/amiga/pcmcia.c linux/arch/m68k/amiga/pcmcia.c
--- v2.1.131/linux/arch/m68k/amiga/pcmcia.c	Mon Aug  3 17:48:26 1998
+++ linux/arch/m68k/amiga/pcmcia.c	Thu Dec 17 09:06:25 1998
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
+#include <linux/timer.h>
 #include <asm/amigayle.h>
 #include <asm/amipcmcia.h>
 
@@ -26,7 +27,7 @@
 	unsigned char b;
 
 	gayle_reset = 0x00;
-	while (jiffies - reset_start_time < 1*HZ/100);
+	while (time_before(jiffies, reset_start_time + 1*HZ/100));
 	b = gayle_reset;
 }
 
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c
--- v2.1.131/linux/arch/m68k/atari/atakeyb.c	Mon Aug  3 12:45:44 1998
+++ linux/arch/m68k/atari/atakeyb.c	Thu Dec 17 09:06:29 1998
@@ -825,7 +825,7 @@
     /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's
      * self-test is finished */
     self_test_last_rcv = jiffies;
-    while( jiffies < self_test_last_rcv + HZ/4 )
+    while (time_before(jiffies, self_test_last_rcv + HZ/4))
 	barrier();
     /* if not incremented: no 0xf1 received */
     if (ikbd_self_test == 1)
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/bvme6000/bvmeints.c linux/arch/m68k/bvme6000/bvmeints.c
--- v2.1.131/linux/arch/m68k/bvme6000/bvmeints.c	Tue Jun 23 10:01:20 1998
+++ linux/arch/m68k/bvme6000/bvmeints.c	Thu Dec 17 09:06:29 1998
@@ -119,9 +119,12 @@
 void bvme6000_process_int (unsigned long vec, struct pt_regs *fp)
 {
 	if (vec > 255)
-		panic ("bvme6000_process_int: Illegal vector %ld", vec);
-	irq_tab[vec].count++;
-	irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+		printk ("bvme6000_process_int: Illegal vector %ld", vec);
+	else
+	{
+		irq_tab[vec].count++;
+		irq_tab[vec].handler(vec, irq_tab[vec].dev_id, fp);
+	}
 }
 
 int bvme6000_get_irq_list (char *buf)
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/bvme6000/config.c linux/arch/m68k/bvme6000/config.c
--- v2.1.131/linux/arch/m68k/bvme6000/config.c	Tue Jun 23 10:01:20 1998
+++ linux/arch/m68k/bvme6000/config.c	Thu Dec 17 09:06:29 1998
@@ -91,8 +91,7 @@
 
 static void bvme6000_get_model(char *model)
 {
-    /* XXX Need to detect if BVME4000 or BVME6000 */
-    sprintf(model, "BVME6000");
+    sprintf(model, "BVME%d000", m68k_cputype == CPU_68060 ? 6 : 4);
 }
 
 
@@ -152,13 +151,17 @@
     pit->pbddr	= 0xf3;	/* Mostly outputs */
     pit->pcdr	= 0x01;	/* PA transceiver disabled */
     pit->pcddr	= 0x03;	/* WDOG disable */
+
+    /* Disable snooping for Ethernet and VME accesses */
+
+    bvme_acr_addrctl = 0;
 }
 
 
 void bvme6000_abort_int (int irq, void *dev_id, struct pt_regs *fp)
 {
         unsigned long *new = (unsigned long *)vectors;
-        unsigned long *old = (unsigned long *)0xf8000000;;
+        unsigned long *old = (unsigned long *)0xf8000000;
 
         /* Wait for button release */
 	while (*config_reg_ptr & BVME_ABORT_STATUS)
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.1.131/linux/arch/m68k/config.in	Thu Nov 12 16:21:18 1998
+++ linux/arch/m68k/config.in	Thu Dec 17 09:06:29 1998
@@ -53,22 +53,11 @@
 bool '68030 support' CONFIG_M68030
 bool '68040 support' CONFIG_M68040
 bool '68060 support' CONFIG_M68060
-if [ "$CONFIG_M68020" = "n" -a "$CONFIG_M68030" = "n" ]; then
-  if [ "$CONFIG_M68040" = "y" -a "$CONFIG_M68060" = "n" ]; then
-    bool 'Use 68040 specific optimizations' CONFIG_OPTIMIZE_040
-  fi
-  if [ "$CONFIG_M68040" = "n" -a "$CONFIG_M68060" = "y" ]; then
-    bool 'Use 68060 specific optimizations' CONFIG_OPTIMIZE_060
-  fi
-fi
-if [ "$CONFIG_VME" = "y" -a "$CONFIG_M68060" = "y" ]; then
-  define_bool CONFIG_060_WRITETHROUGH y
-fi
 bool 'Advanced configuration options' CONFIG_ADVANCED
 if [ "$CONFIG_ADVANCED" = "y" ]; then
   bool 'Use read-modify-write instructions' CONFIG_RMW_INSNS
   bool 'Use one physical chunk of memory only' CONFIG_SINGLE_MEMORY_CHUNK
-  if [ "$CONFIG_M68060" = "y" -a "$CONFIG_VME" = "n" ]; then
+  if [ "$CONFIG_M68060" = "y" ]; then
     bool 'Use write-through caching for 68060 supervisor accesses' CONFIG_060_WRITETHROUGH
   fi
 fi
@@ -157,7 +146,7 @@
     bool 'A4091 SCSI support' CONFIG_A4091_SCSI
     bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
     bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI
-    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
+#    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
 #    bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
   fi
 fi
@@ -230,10 +219,10 @@
   bool 'Macintosh onboard SONIC ethernet' CONFIG_MACSONIC
 fi
 if [ "$CONFIG_VME" = "y" -a "$CONFIG_MVME16x" = "y" ]; then
-  bool 'MVME16x Ethernet support' CONFIG_MVME16x_NET
+  tristate 'MVME16x Ethernet support' CONFIG_MVME16x_NET
 fi
 if [ "$CONFIG_VME" = "y" -a "$CONFIG_BVME6000" = "y" ]; then
-  bool 'BVME6000 Ethernet support' CONFIG_BVME6000_NET
+  tristate 'BVME6000 Ethernet support' CONFIG_BVME6000_NET
 fi
 if [ "$CONFIG_ATARI" = "y" ]; then
   tristate 'Atari Lance support' CONFIG_ATARILANCE
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/defconfig linux/arch/m68k/defconfig
--- v2.1.131/linux/arch/m68k/defconfig	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/defconfig	Thu Dec 17 09:06:29 1998
@@ -28,8 +28,6 @@
 CONFIG_M68030=y
 CONFIG_M68040=y
 # CONFIG_M68060 is not set
-# CONFIG_OPTIMIZE_040 is not set
-# CONFIG_OPTIMIZE_060 is not set
 # CONFIG_ADVANCED is not set
 # CONFIG_SINGLE_MEMORY_CHUNK is not set
 # CONFIG_RMW_INSNS is not set
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/kernel/Makefile linux/arch/m68k/kernel/Makefile
--- v2.1.131/linux/arch/m68k/kernel/Makefile	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/kernel/Makefile	Thu Dec 17 09:06:29 1998
@@ -26,10 +26,13 @@
 
 head.o: head.S m68k_defs.h
 
-m68k_defs.h: m68k_defs.c m68k_defs.head $(TOPDIR)/include/linux/sched.h
-	$(CC) ${CFLAGS} -S m68k_defs.c
+m68k_defs.h: m68k_defs.c m68k_defs.head
+	rm -f m68k_defs.d
+	SUNPRO_DEPENDENCIES="m68k_defs.d m68k_defs.h" \
+	$(CC) $(filter-out -MD,$(CFLAGS)) -S m68k_defs.c
 	cp m68k_defs.head m68k_defs.h
-	sed -n < m68k_defs.s >> m68k_defs.h '/^#define/s/ #/ /p'
+	grep '^#define' m68k_defs.s >> m68k_defs.h
 	rm m68k_defs.s
+-include m68k_defs.d
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/kernel/m68k_defs.c linux/arch/m68k/kernel/m68k_defs.c
--- v2.1.131/linux/arch/m68k/kernel/m68k_defs.c	Tue Feb 17 13:12:45 1998
+++ linux/arch/m68k/kernel/m68k_defs.c	Thu Dec 17 09:06:29 1998
@@ -12,7 +12,7 @@
 #include <linux/sched.h>
 
 #define DEFINE(sym, val) \
-	asm volatile("\n#define " #sym " %0" : : "i" (val))
+	asm volatile("\n#define " #sym " %c0" : : "i" (val))
 
 int main(void)
 {
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.1.131/linux/arch/m68k/kernel/m68k_ksyms.c	Fri Oct  9 13:27:05 1998
+++ linux/arch/m68k/kernel/m68k_ksyms.c	Thu Dec 17 09:06:29 1998
@@ -49,6 +49,7 @@
 EXPORT_SYMBOL(local_bh_count);
 EXPORT_SYMBOL(enable_irq);
 EXPORT_SYMBOL(disable_irq);
+EXPORT_SYMBOL(kernel_set_cachemode);
 
 /* Networking helper routines. */
 EXPORT_SYMBOL(csum_partial_copy);
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.1.131/linux/arch/m68k/kernel/process.c	Thu Nov 12 16:21:18 1998
+++ linux/arch/m68k/kernel/process.c	Thu Dec 17 09:06:29 1998
@@ -40,7 +40,6 @@
  */
 static struct vm_area_struct init_mmap = INIT_MMAP;
 static struct fs_struct init_fs = INIT_FS;
-static struct file * init_fd_array[NR_OPEN] = { NULL, };
 static struct files_struct init_files = INIT_FILES;
 static struct signal_struct init_signals = INIT_SIGNALS;
 struct mm_struct init_mm = INIT_MM;
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c
--- v2.1.131/linux/arch/m68k/mac/config.c	Fri Oct  9 13:27:06 1998
+++ linux/arch/m68k/mac/config.c	Thu Dec 17 09:06:29 1998
@@ -100,17 +100,15 @@
 extern void mac_debugging_long(int, long);
 
 #ifdef CONFIG_MAGIC_SYSRQ
-
-/* XXX FIXME: Atari scancodes still */
 static char mac_sysrq_xlate[128] =
-	"\000\0331234567890-=\177\t"				/* 0x00 - 0x0f */
-	"qwertyuiop[]\r\000as"					/* 0x10 - 0x1f */
-	"dfghjkl;'`\000\\zxcv"					/* 0x20 - 0x2f */
-	"bnm,./\000\000\000 \000\201\202\203\204\205"		/* 0x30 - 0x3f */
-	"\206\207\210\211\212\000\000\000\000\000-\000\000\000+\000"/* 0x40 - 0x4f */
-	"\000\000\000\177\000\000\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
-	"\000\000\000()/*789456123"				/* 0x60 - 0x6f */
-	"0.\r\000\000\000\000\000\000\000\000\000\000\000\000\000";	/* 0x70 - 0x7f */
+	"\000sdfghzxcv\000bqwer"				/* 0x00 - 0x0f */
+	"yt123465=97-80)o"					/* 0x10 - 0x1f */
+	"u(ip\rlj'k;\\,/nm."					/* 0x20 - 0x2f */
+	"\t `\000\033\000\000\000\000\000\000\000\000\000\000\000"	/* 0x30 - 0x3f */
+	"\000.\000*\000+\000\000\000\000\000/\r\000-\000"	/* 0x40 - 0x4f */
+	"\000\00001234567a89\000\000\000"			/* 0x50 - 0x5f */
+	"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"  /* 0x60 - 0x6f */
+	"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"; /* 0x70 - 0x7f */
 #endif
 
 extern void (*kd_mksound)(unsigned int, unsigned int);
@@ -336,7 +334,7 @@
 #endif
     kd_mksound		 = mac_mksound;
 #ifdef CONFIG_MAGIC_SYSRQ
-    mach_sysrq_key = 98;          /* HELP */
+    mach_sysrq_key = 114;         /* HELP */
     mach_sysrq_shift_state = 8;   /* Alt */
     mach_sysrq_shift_mask = 0xff; /* all modifiers except CapsLock */
     mach_sysrq_xlate = mac_sysrq_xlate;
@@ -399,10 +397,10 @@
 	 *	
 	 */
 	 
-	{	MAC_MODEL_II,	"II",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
-	{	MAC_MODEL_IIX,	"IIx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
-	{	MAC_MODEL_IICX,	"IIcx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
-	{	MAC_MODEL_SE30, "SE/30",	MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_NUBUS},
+	{	MAC_MODEL_II,	"II",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_IIX,	"IIx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_IICX,	"IIcx",		MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_SE30, "SE/30",	MAC_ADB_II,	MAC_VIA_II,	MAC_SCSI_OLD,	MAC_IDE_NONE,	MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	
 	/*
 	 *	Weirdified MacII hardware - all subtley different. Gee thanks
@@ -461,11 +459,11 @@
 	 *	Performa - more LC type machines
 	 */
 
-	{	MAC_MODEL_P460,  "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci,   MAC_SCSI_OLD, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_P460,  "Performa 460", MAC_ADB_IISI, MAC_VIA_IIci,   MAC_SCSI_OLD,    MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P475,  "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	{	MAC_MODEL_P475F, "Performa 475", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE, MAC_NUBUS},
 	{	MAC_MODEL_P520,  "Performa 520", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
-	{	MAC_MODEL_P550,  "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
+	{	MAC_MODEL_P550,  "Performa 550", MAC_ADB_CUDA, MAC_VIA_IIci,   MAC_SCSI_OLD,    MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P575,  "Performa 575", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_P588,  "Performa 588", MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_QUADRA, MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
 	{	MAC_MODEL_TV,    "TV",           MAC_ADB_CUDA, MAC_VIA_QUADRA, MAC_SCSI_OLD,	MAC_IDE_NONE, MAC_SCC_II,	MAC_ETHER_NONE,	MAC_NUBUS},
@@ -551,7 +549,7 @@
 			m++;
 		}
 		if(m->ident==-1)
-			mac_boom(5);
+			panic("mac model config data corrupt!\n");
 	}
 
 	/*
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c
--- v2.1.131/linux/arch/m68k/mac/debug.c	Fri Oct  9 13:27:06 1998
+++ linux/arch/m68k/mac/debug.c	Thu Dec 17 09:06:29 1998
@@ -36,6 +36,9 @@
 extern unsigned long mac_videodepth;
 extern unsigned long mac_rowbytes;
 
+extern void mac_serial_print(char *);
+
+#define DEBUG_HEADS
 #define DEBUG_SCREEN
 #define DEBUG_SERIAL
 
@@ -129,121 +132,6 @@
 #endif
 }
 
-/*
- * Penguin - used by head.S console; obsolete
- */
-char that_penguin[]={
-#include "that_penguin.h"
-};
-
-#ifdef DEBUG_SCREEN
-/* 
- * B/W version of penguin, unfinished - any takers??
- */
-static char bw_penguin[]={
-#include "bw_penguin.h"
-};
-#endif
-
-void mac_debugging_penguin(int peng)
-{
-#ifdef DEBUG_SCREEN
-	unsigned char *pengoffset;
-	unsigned char *pptr;
-	unsigned char *bwpdptr=bw_penguin;
-	int i;
-#endif
-
-#ifdef DEBUG_SERIAL
-	printk("Penguin: #%d !\n", peng);
-#endif
-
-#ifdef DEBUG_SCREEN
-	if (!MACH_IS_MAC) 
-		return;
-
-	if (mac_videodepth ==1) 
-		pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
-			   +5*peng;
-	else
-		pengoffset=(unsigned char *)(mac_videobase+80*mac_rowbytes)
-			   +20*peng;
-	
-	pptr=pengoffset;
-	
-	for(i=0;i<36;i++)
-	{
-		memcpy(pptr,bwpdptr,4);
-		bwpdptr+=4;
-		pptr+=mac_rowbytes;
-	}
-#endif
-}
-
-#ifdef DEBUG_SCREEN
-/*
- * B/W version of flaming Mac, unfinished (see above).
- */
-static char bw_kaboom_map[]={
-#include "bw_mac.h"
-};
-#endif
-
-#ifdef DEBUG_SCREEN
-static void mac_boom_boom(void)
-{
-	static unsigned char *boomoffset=NULL;
-	unsigned char *pptr;
-	unsigned char *bwpdptr=bw_kaboom_map;
-	int i;
-	
-#ifdef DEBUG_SERIAL
-	printk("BOOM !\n");
-#endif
-
-	if (!MACH_IS_MAC) 
-		return;
-
-	if(!boomoffset)
-		if (mac_videodepth == 1) {
-			boomoffset=(unsigned char *)(mac_videobase+160*mac_rowbytes);
-		} else {
-			boomoffset=(unsigned char *)(mac_videobase+256*mac_rowbytes);
-		}
-	else
-		if (mac_videodepth == 1)
-			boomoffset+=5;
-		else
-			boomoffset+=32;	
-
-	pptr=boomoffset;
-	
-	for(i=0;i<36;i++)
-	{
-		memcpy(pptr,bwpdptr,4);
-		bwpdptr+=4;
-		pptr+=mac_rowbytes;
-	}
-}
-#endif
-
-void mac_boom(int booms)
-{
-#ifdef DEBUG_SCREEN
-	int i;
-#endif
-
-	if (!MACH_IS_MAC) 
-		return;
-
-#ifdef DEBUG_SCREEN
-	for(i=0;i<booms;i++)
-		mac_boom_boom();
-	while(1);
-#endif
-}
-
-
 #ifdef DEBUG_SERIAL
 /*
  * TODO: serial debug code
@@ -284,6 +172,29 @@
 	NULL
 };
 
+/*
+ * Crude hack to get console output to the screen before the framebuffer
+ * is initialized (happens a lot later in 2.1!).
+ * We just use the console routines declared in head.S, this will interfere
+ * with regular framebuffer console output and should be used exclusively
+ * to debug kernel problems manifesting before framebuffer init (aka WSOD)
+ *
+ * To keep this hack from interfering with the regular console driver, either
+ * deregister this driver before/on framebuffer console init, or silence this
+ * function after the fbcon driver is running (will lose console messages!?).
+ * To debug real early bugs, need to write a 'mac_register_console_hack()'
+ * that is called from start_kernel() before setup_arch() and just registers
+ * this driver if Mac.
+ */
+
+void mac_debug_console_write (struct console *co, const char *str,
+			      unsigned int count)
+{
+	mac_serial_print(str);
+}
+
+
+
 /* Mac: loops_per_sec min. 1900000 ^= .5 us; MFPDELAY was 0.6 us*/
 
 #define uSEC 1
@@ -496,9 +407,16 @@
 	mac_console_driver.wait_key = mac_sccb_console_wait_key;
 	scc_port = 1;
     }
+#endif
+#ifdef DEBUG_HEADS
+    if (   !strcmp( m68k_debug_device, "scn"  )
+        || !strcmp( m68k_debug_device, "con" )) {
+	/* display, using head.S console routines */
+	mac_console_driver.write = mac_debug_console_write;
+    }
+#endif
     if (mac_console_driver.write)
 	register_console(&mac_console_driver);
-#endif
 }
 
 /*
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mac/macints.c linux/arch/m68k/mac/macints.c
--- v2.1.131/linux/arch/m68k/mac/macints.c	Fri Oct  9 13:27:06 1998
+++ linux/arch/m68k/mac/macints.c	Thu Dec 17 09:06:29 1998
@@ -163,7 +163,7 @@
 static unsigned long *mac_irqs[8];
 
 /*
- * VIA2 / RBV register base pointers
+ * VIA/RBV/OSS/PSC register base pointers
  */
 
 volatile unsigned char *via2_regp=(volatile unsigned char *)VIA2_BAS;
@@ -247,7 +247,7 @@
 
 		/* yes, this is messy - the IIfx deserves a class of his own */
 		if (macintosh_config->ident == MAC_MODEL_IIFX) {
-			/* no real VIA2, the OSS seems _very_different */	
+			/* no real VIA2, the OSS seems _very_ different */	
 			via2_is_oss = 1;
 			/* IIfx has OSS, at a different base address than RBV */
 			rbv_regp = (unsigned char *) OSS_BAS;
@@ -459,7 +459,7 @@
 	if (irq == IRQ_IDX(IRQ_MAC_SCSI)) {
 		/*
 		 * Set vPCR for SCSI interrupts. (what about RBV here?)
-		 * 980429 MS: RBV is ok, OSS seems to be differentt
+		 * 980429 MS: RBV is ok, OSS seems to be different
 		 */
 		if (!via2_is_oss)
 			if (macintosh_config->scsi_type == MAC_SCSI_OLD) {
@@ -602,7 +602,10 @@
 
 /*
  * In opposite to {en,dis}able_irq, requests between turn{off,on}_irq are not
- * "stored". This is done with the VIA interrupt enable register
+ * "stored". This is done with the VIA interrupt enable register on VIAs.
+ *
+ * Note: Using these functions on non-VIA/OSS/PSC ints will panic, or at least 
+ * have undesired side effects.
  */
 
 void mac_turnon_irq( unsigned int irq )
@@ -615,14 +618,14 @@
 	if (!via) 
 		return;
 
-	if (srcidx == SRC_VIA2 && via2_is_rbv)
+	if (srcidx == SRC_VIA2 && via2_is_rbv)		/* RBV as VIA2 */
 	        via_write(via, rIER, via_read(via, rIER)|0x80|(1<<(irqidx)));
-	else if (srcidx == SRC_VIA2 && via2_is_oss)
+	else if (srcidx == SRC_VIA2 && via2_is_oss)	/* OSS */
 		via_write(oss_regp, oss_map[irqidx]+8, 2);
-	else if (srcidx > SRC_VIA2)
+	else if (srcidx > SRC_VIA2)			/* hope AVs have VIA2 */
 	        via_write(via, (0x104 + 0x10*srcidx), 
 	        	via_read(via, (0x104 + 0x10*srcidx))|0x80|(1<<(irqidx)));
-	else
+	else						/* VIA1+2 */
 	        via_write(via, vIER, via_read(via, vIER)|0x80|(1<<(irqidx)));
 
 }
@@ -637,9 +640,9 @@
 	if (!via) 
 		return;
 
-	if (srcidx == SRC_VIA2 && via2_is_rbv)
+	if (srcidx == SRC_VIA2 && via2_is_rbv)		/* RBV as VIA2 */
 		via_write(via, rIER, (via_read(via, rIER)&(1<<irqidx)));
-	else if (srcidx == SRC_VIA2 && via2_is_oss)
+	else if (srcidx == SRC_VIA2 && via2_is_oss)	/* OSS */
 		via_write(oss_regp, oss_map[irqidx]+8, 0);
 	/*
 	 *	VIA2 is fixed. The stuff above VIA2 is for later
@@ -648,7 +651,7 @@
 	else if (srcidx > SRC_VIA2)
 	        via_write(via, (0x104 + 0x10*srcidx), 
 	        	via_read(via, (0x104 + 0x10*srcidx))|(1<<(irqidx)));
-	else
+	else						/* VIA1+2 */
 		via_write(via, vIER, (via_read(via, vIER)&(1<<irqidx)));
 }
 
@@ -785,7 +788,7 @@
 void mac_default_handler(int irq, void *dev_id, struct pt_regs *regs)
 {
 #ifdef DEBUG_VIA
-	printk("Unexpected IRQ %d\n", irq);
+	printk("Unexpected IRQ %d on device %p\n", irq, dev_id);
 #endif
 }
 
@@ -1310,7 +1313,7 @@
 	if(events==0)
 	{
 #ifdef DEBUG_VIA
-		printk("rbv_irq: nothing pending, flags %x mask %x!\n",
+		printk("psc_irq: nothing pending, flags %x mask %x!\n",
 			via_read(via, pIFR), via_read(via,pIER));
 #endif
 		mac_irqs[srcidx][7]++;
@@ -1319,7 +1322,7 @@
 
 #ifdef DEBUG_VIA	
 	/*
-	 * limited verbosity for RBV interrupts (add more if needed)
+	 * limited verbosity for PSC interrupts (add more if needed)
 	 */
 	if ( srcidx == 1 && events != 1<<3 && events != 1<<1 )		/* SCSI IRQ */
 		printk("psc_irq: irq %d srcidx+1 %d events %x !\n", irq, srcidx+1, events);
@@ -1506,6 +1509,10 @@
 		else
 			map = ~via_read(via2_regp, vBufA);
 		
+#ifdef DEBUG_NUBUS_INT
+		printk("nubus_irq: map %x mask %x\n", map, nubus_active);
+#endif
+
 		if( (map = (map&nubus_active)) ==0 ) {
 #ifdef DEBUG_NUBUS_INT
 			printk("nubus_irq: nothing pending, map %x mask %x\n", 
@@ -1514,9 +1521,6 @@
 			nubus_irqs[7]++;
 			break;
 		}
-#ifdef DEBUG_NUBUS_INT
-		printk("nubus_irq: map %x mask %x\n", map, nubus_active);
-#endif
 
 		if(ct++>2)
 		{
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mac/mackeyb.c linux/arch/m68k/mac/mackeyb.c
--- v2.1.131/linux/arch/m68k/mac/mackeyb.c	Fri Oct  9 13:27:06 1998
+++ linux/arch/m68k/mac/mackeyb.c	Fri Dec 18 08:06:39 1998
@@ -1,5 +1,12 @@
 /*
- *  linux/arch/m68k/mac/mackeyb.c
+ * linux/arch/m68k/mac/mackeyb.c
+ *
+ * Keyboard driver for Macintosh computers.
+ *
+ * Adapted from drivers/macintosh/key_mac.c and arch/m68k/atari/akakeyb.c 
+ * (see that file for its authors and contributors).
+ *
+ * Copyright (C) 1997 Michael Schmitz.
  *
  * 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
@@ -10,6 +17,7 @@
  * misc. keyboard stuff (everything not in adb-bus.c or keyb_m68k.c)
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/kd.h>
@@ -59,8 +67,15 @@
 static void mac_leds_done(struct adb_request *);
 static void keyboard_input(unsigned char *, int, struct pt_regs *);
 static void mouse_input(unsigned char *, int, struct pt_regs *);
-/* Hook for mouse driver */
-void (*adb_mouse_interrupt_hook) (char *, int);
+
+#ifdef CONFIG_ADBMOUSE
+/* XXX: Hook for mouse driver */
+void (*adb_mouse_interrupt_hook)(unsigned char *, int);
+int adb_emulate_buttons = 0;
+int adb_button2_keycode = 0x7d;	/* right control key */
+int adb_button3_keycode = 0x7c; /* right option key */
+#endif
+
 /* The mouse driver - for debugging */
 extern void adb_mouse_interrupt(char *, int);
 /* end keyb */
@@ -275,9 +290,11 @@
  	kbd = kbd_table + fg_console;
 	up_flag = (keycode & 0x80);
         keycode &= 0x7f;
+
 	if (!repeat)
 		del_timer(&repeat_timer);
 
+#ifdef CONFIG_ADBMOUSE
 	/*
 	 * XXX: Add mouse button 2+3 fake codes here if mouse open.
 	 *	As we only report up/down events, keep track of faked buttons.
@@ -289,7 +306,8 @@
 	 *	(wanted: command and alt/option, or KP= and KP( ...)
 	 *	Debug version; might be rewritten to be faster on normal keys.
 	 */
-	if (adb_mouse_interrupt_hook || console_loglevel >= 8) {
+	if (adb_emulate_buttons 
+	    && (adb_mouse_interrupt_hook || console_loglevel >= 8)) {
 		unsigned char button, button2, button3, fake_event;
 		static unsigned char button2state=0, button3state=0; /* up */
 		/* faked ADB packet */
@@ -297,21 +315,20 @@
 
 		button = 0;
 		fake_event = 0;
-		switch (keycode) {	/* which 'button' ? */
-			case 0x7c:	/* R-option */
-				button2 = (!up_flag);		/* new state */
-				if (button2 != button2state)	/* change ? */
-					button = 2; 
-				button2state = button2;		/* save state */
-				fake_event = 2;
-				break; 
-			case 0x7d:	/* R-control */
-				button3 = (!up_flag);		/* new state */
-				if (button3 != button3state)	/* change ? */ 
-					button = 3; 
-				button3state = button3; 	/* save state */
-				fake_event = 3;
-				break; 
+		if (keycode == adb_button2_keycode) {	/* which 'button' ? */
+			/* R-option */
+			button2 = (!up_flag);		/* new state */
+			if (button2 != button2state)	/* change ? */
+				button = 2; 
+			button2state = button2;		/* save state */
+			fake_event = 2;
+		} else if (keycode == adb_button3_keycode) {
+			/* R-control */
+			button3 = (!up_flag);		/* new state */
+			if (button3 != button3state)	/* change ? */ 
+				button = 3; 
+			button3state = button3; 	/* save state */
+			fake_event = 3;
 		}
 #ifdef DEBUG_ADBMOUSE
 		if (fake_event && console_loglevel >= 8)
@@ -340,6 +357,7 @@
 		if (fake_event)
 			return;
 	}
+#endif /* CONFIG_ADBMOUSE */
 
 	/*
 	 * Convert R-shift/control/option to L version.
@@ -365,16 +383,18 @@
 		 * transition into a key-down transition.
 		 * MSch: need to turn each caps-lock event into a down-up
 		 * double event (keyboard code assumes caps-lock is a toggle)
+		 * 981127: fix LED behavior (kudos atong!)
 		 */
-#if 0
-		if (keycode == 0x39 && up_flag && vc_kbd_led(kbd, VC_CAPSLOCK))
-			up_flag = 0;
-#else
-		if (keycode == 0x39) {
+		switch (keycode) {
+		case 0x39:
 			handle_scancode(keycode);	/* down */
 			up_flag = 0x80;			/* see below ... */
+		 	mark_bh(KEYBOARD_BH);
+			break;
+		 case 0x47:
+		 	mark_bh(KEYBOARD_BH);
+		 	break;
 		}
-#endif
 	}
 
 	handle_scancode(keycode + up_flag);
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mac/via6522.c linux/arch/m68k/mac/via6522.c
--- v2.1.131/linux/arch/m68k/mac/via6522.c	Fri Oct  9 13:27:06 1998
+++ linux/arch/m68k/mac/via6522.c	Thu Dec 17 09:06:29 1998
@@ -304,10 +304,11 @@
 		unsigned long flags;
 		unsigned long *reset_hook;
 
-		save_flags(flags);
-		cli();
-
 		/* need ROMBASE in booter */
+		/* indeed, plus need to MAP THE ROM !! */
+
+		if (mac_bi_data.rombase == 0)
+			mac_bi_data.rombase = 0x40800000;
 
 		/* works on some */
 		rom_reset = (void *) (mac_bi_data.rombase + 0xa);
@@ -318,12 +319,22 @@
 		printk("ROM reset hook: %p\n", *reset_hook);
 		rom_reset = *reset_hook;
 #endif
+		if (macintosh_config->ident == MAC_MODEL_SE30) {
+			/*
+			 * MSch: Machines known to crash on ROM reset ...
+			 */
+			printk("System halted.\n");
+			while(1);
+		} else {
+			save_flags(flags);
+			cli();
 
-		rom_reset();
+			rom_reset();
 
-		restore_flags(flags);
+			restore_flags(flags);
+		}
 
-		/* We never make it this far... */
+		/* We never make it this far... it usually panics above. */
 		printk ("Restart failed.  Please restart manually.\n");
 
 		/* XXX - delay do we need to spin here ? */
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mm/fault.c linux/arch/m68k/mm/fault.c
--- v2.1.131/linux/arch/m68k/mm/fault.c	Mon Aug  3 12:45:44 1998
+++ linux/arch/m68k/mm/fault.c	Thu Dec 17 09:06:30 1998
@@ -8,6 +8,7 @@
 #include <linux/mm.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
+#include <linux/interrupt.h>
 
 #include <asm/setup.h>
 #include <asm/traps.h>
@@ -32,8 +33,7 @@
 asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
 			      unsigned long error_code)
 {
-	struct task_struct *tsk = current;
-	struct mm_struct *mm = tsk->mm;
+	struct mm_struct *mm = current->mm;
 	struct vm_area_struct * vma;
 	unsigned long fixup;
 	int write;
@@ -41,9 +41,17 @@
 #ifdef DEBUG
 	printk ("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld, %p\n",
 		regs->sr, regs->pc, address, error_code,
-		tsk->mm->pgd);
+		current->mm->pgd);
 #endif
 
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_interrupt() || mm == &init_mm)
+		goto no_context;
+
 	down(&mm->mmap_sem);
 
 	vma = find_vma(mm, address);
@@ -86,7 +94,14 @@
 			if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
 				goto bad_area;
 	}
-	handle_mm_fault(current, vma, address, write);
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	if (!handle_mm_fault(current, vma, address, write))
+		goto do_sigbus;
 
 	/* There seems to be a missing invalidate somewhere in do_no_page.
 	 * Until I found it, this one cures the problem and makes
@@ -106,10 +121,15 @@
 
 	/* User mode accesses just cause a SIGSEGV */
 	if (user_mode(regs)) {
-		force_sig (SIGSEGV, tsk);
+		siginfo_t info;
+		info.si_signo = SIGSEGV;
+		info.si_code = SEGV_MAPERR;
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, current);
 		return 1;
 	}
 
+no_context:
 	/* Are we prepared to handle this kernel fault?  */
 	if ((fixup = search_exception_table(regs->pc)) != 0) {
 		struct pt_regs *tregs;
@@ -135,6 +155,23 @@
 	printk(" at virtual address %08lx\n",address);
 	die_if_kernel("Oops", regs, error_code);
 	do_exit(SIGKILL);
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+do_sigbus:
+	up(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+	force_sig(SIGBUS, current);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!user_mode(regs))
+		goto no_context;
 
 	return 1;
 }
diff -u --recursive --new-file v2.1.131/linux/arch/m68k/mvme16x/16xints.c linux/arch/m68k/mvme16x/16xints.c
--- v2.1.131/linux/arch/m68k/mvme16x/16xints.c	Tue Jun 23 10:01:21 1998
+++ linux/arch/m68k/mvme16x/16xints.c	Thu Dec 17 09:06:30 1998
@@ -106,9 +106,12 @@
 void mvme16x_process_int (unsigned long vec, struct pt_regs *fp)
 {
 	if (vec < 64 || vec > 255)
-		panic ("mvme16x_process_int: Illegal vector %ld", vec);
-	irq_tab[vec-64].count++;
-	irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp);
+		printk ("mvme16x_process_int: Illegal vector %ld", vec);
+	else
+	{
+		irq_tab[vec-64].count++;
+		irq_tab[vec-64].handler(vec, irq_tab[vec-64].dev_id, fp);
+	}
 }
 
 int mvme16x_get_irq_list (char *buf)
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.1.131/linux/arch/ppc/8xx_io/enet.c	Mon Oct  5 13:13:35 1998
+++ linux/arch/ppc/8xx_io/enet.c	Mon Dec 21 08:37:20 1998
@@ -1,4 +1,5 @@
 /*
+ * $Id: enet.c,v 1.8 1998/11/15 19:58:07 cort Exp $
  * Ethernet driver for Motorola MPC8xx.
  * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
  *
@@ -657,7 +658,7 @@
 
 	cp = cpmp;	/* Get pointer to Communication Processor */
 
-	immap = (immap_t *)MBX_IMAP_ADDR;	/* and to internal registers */
+	immap = (immap_t *)IMAP_ADDR;	/* and to internal registers */
 
 	/* Allocate some private information.
 	*/
@@ -719,11 +720,11 @@
 	 * These are relative offsets in the DP ram address space.
 	 * Initialize base addresses for the buffer descriptors.
 	 */
-	i = mbx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
+	i = m8xx_cpm_dpalloc(sizeof(cbd_t) * RX_RING_SIZE);
 	ep->sen_genscc.scc_rbase = i;
 	cep->rx_bd_base = (cbd_t *)&cp->cp_dpmem[i];
 
-	i = mbx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
+	i = m8xx_cpm_dpalloc(sizeof(cbd_t) * TX_RING_SIZE);
 	ep->sen_genscc.scc_tbase = i;
 	cep->tx_bd_base = (cbd_t *)&cp->cp_dpmem[i];
 
@@ -912,4 +913,3 @@
 
 	return 0;
 }
-
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/Makefile linux/arch/ppc/Makefile
--- v2.1.131/linux/arch/ppc/Makefile	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/Makefile	Mon Dec 21 08:37:20 1998
@@ -16,8 +16,6 @@
 
 ifeq ($(shell uname -m),ppc)
 CHECKS		= checks
-else
-CROSS_COMPILE	= ppc-linux-elf-
 endif
 
 ASFLAGS		=
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/amiga/bootinfo.c linux/arch/ppc/amiga/bootinfo.c
--- v2.1.131/linux/arch/ppc/amiga/bootinfo.c	Thu Aug  6 14:06:29 1998
+++ linux/arch/ppc/amiga/bootinfo.c	Mon Dec 21 08:37:20 1998
@@ -17,8 +17,8 @@
 extern char cmd_line[CL_SIZE];
 
 int num_memory = 0;
-extern struct mem_info memory[NUM_MEMINFO];
-extern struct mem_info ramdisk;
+struct mem_info memory[NUM_MEMINFO];
+struct mem_info ramdisk;
 
 extern int amiga_parse_bootinfo(const struct bi_record *);
 extern int atari_parse_bootinfo(const struct bi_record *);
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/amiga/config.c linux/arch/ppc/amiga/config.c
--- v2.1.131/linux/arch/ppc/amiga/config.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/amiga/config.c	Mon Dec 21 08:37:20 1998
@@ -742,7 +742,7 @@
 static void amiga_serial_putc(char c)
 {
     custom.serdat = (unsigned char)c | 0x100;
-    iobarrier ();
+    iobarrier_rw ();
     while (!(custom.serdatr & 0x2000))
        ;
 }
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/boot/Makefile linux/arch/ppc/boot/Makefile
--- v2.1.131/linux/arch/ppc/boot/Makefile	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/boot/Makefile	Mon Dec 21 08:37:20 1998
@@ -48,6 +48,9 @@
 CFLAGS += -DCONFIG_MBX
 else
 OBJECTS += vreset.o kbd.o
+ ifeq ($(CONFIG_SERIAL_CONSOLE),y)
+  OBJECTS += ns16550.o
+ endif
 endif
 
 all:	zImage
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/boot/misc.c linux/arch/ppc/boot/misc.c
--- v2.1.131/linux/arch/ppc/boot/misc.c	Mon Oct  5 13:13:36 1998
+++ linux/arch/ppc/boot/misc.c	Mon Dec 21 08:37:20 1998
@@ -1,7 +1,7 @@
 /*
  * misc.c
  *
- * $Id: misc.c,v 1.52 1998/09/19 01:21:24 cort Exp $
+ * $Id: misc.c,v 1.53 1998/12/15 17:40:15 cort Exp $
  * 
  * Adapted for PowerPC by Gary Thomas
  *
@@ -12,7 +12,7 @@
 #include <linux/types.h>
 #include "../coffboot/zlib.h"
 #include "asm/residual.h"
-#include <elf.h>
+#include <linux/elf.h>
 #include <linux/config.h>
 #include <asm/page.h>
 #include <asm/processor.h>
@@ -23,6 +23,10 @@
 #ifdef CONFIG_FADS
 #include <asm/fads.h>
 #endif
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+#include "ns16550.h"
+struct NS16550 *com_port;
+#endif /* CONFIG_SERIAL_CONSOLE */
 
 /*
  * Please send me load/board info and such data for hardware not
@@ -42,6 +46,7 @@
  * save here and pass to the kernel (command line and board info).
  * On the MBX we grab some known memory holes to hold this information.
  */
+char cmd_preset[] = "console=tty0 console=ttyS0,9600n8";
 char	cmd_buf[256];
 char	*cmd_line = cmd_buf;
 
@@ -108,12 +113,19 @@
 
 tstc(void)
 {
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+	return (CRT_tstc() || NS16550_tstc(com_port));
+#else
 	return (CRT_tstc() );
+#endif /* CONFIG_SERIAL_CONSOLE */
 }
 
 getc(void)
 {
 	while (1) {
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+		if (NS16550_tstc(com_port)) return (NS16550_getc(com_port));
+#endif /* CONFIG_SERIAL_CONSOLE */
 		if (CRT_tstc()) return (CRT_getc());
 	}
 }
@@ -123,6 +135,11 @@
 {
 	int x,y;
 
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+	NS16550_putc(com_port, c);
+	if ( c == '\n' ) NS16550_putc(com_port, '\r');
+#endif /* CONFIG_SERIAL_CONSOLE */
+
 	x = orig_x;
 	y = orig_y;
 
@@ -162,12 +179,21 @@
 	y = orig_y;
 
 	while ( ( c = *s++ ) != '\0' ) {
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+	        NS16550_putc(com_port, c);
+	        if ( c == '\n' ) NS16550_putc(com_port, '\r');
+#endif /* CONFIG_SERIAL_CONSOLE */
+
 		if ( c == '\n' ) {
 			x = 0;
 			if ( ++y >= lines ) {
 				scroll();
 				y--;
 			}
+		} else if (c == '\b') {
+		  if (x > 0) {
+		    x--;
+		  }
 		} else {
 			vidmem [ ( x + cols * y ) * 2 ] = c; 
 			if ( ++x >= cols ) {
@@ -358,6 +384,10 @@
 	_put_MSR(_get_MSR() & ~0x0030);
 	vga_init(0xC0000000);
 
+#if defined(CONFIG_SERIAL_CONSOLE) && !defined(CONFIG_MBX)
+	com_port = (struct NS16550 *)NS16550_init(0);
+#endif /* CONFIG_SERIAL_CONSOLE */
+
 	if (residual)
 		memcpy(hold_residual,residual,sizeof(RESIDUAL));
 #else /* CONFIG_MBX */
@@ -510,6 +540,8 @@
 	puts("\nLinux/PPC load: ");
 	timer = 0;
 	cp = cmd_line;
+	memcpy (cmd_line, cmd_preset, sizeof(cmd_preset));
+	while ( *cp ) putc(*cp++);
 	while (timer++ < 5*1000) {
 		if (tstc()) {
 			while ((ch = getc()) != '\n' && ch != '\r') {
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/coffboot/Makefile linux/arch/ppc/coffboot/Makefile
--- v2.1.131/linux/arch/ppc/coffboot/Makefile	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/coffboot/Makefile	Mon Dec 21 08:37:20 1998
@@ -3,18 +3,6 @@
 #
 # Paul Mackerras	January 1997
 
-# PowerPC (cross) tools
-ifneq ($(shell uname -m),ppc)
-CROSS_COMPILE 	=powerpc-eabi-
-endif
-
-
-# PowerPC (cross) tools
-ifneq ($(shell uname -m),ppc)
-#CROSS_COMPILE 	=powerpc-eabi-
-CROSS_COMPILE  =ppc-linux-elf-
-endif
-
 HOSTCC	= gcc
 HOSTCFLAGS = -O -I$(TOPDIR)/include
 
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/common_defconfig linux/arch/ppc/common_defconfig
--- v2.1.131/linux/arch/ppc/common_defconfig	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/common_defconfig	Mon Dec 21 08:37:20 1998
@@ -45,7 +45,7 @@
 CONFIG_BLK_DEV_IDE_PMAC=y
 CONFIG_PROC_DEVICETREE=y
 # CONFIG_KGDB is not set
-CONFIG_XMON=y
+# CONFIG_XMON is not set
 # CONFIG_TOTALMP is not set
 # CONFIG_BOOTX_TEXT is not set
 
@@ -188,6 +188,7 @@
 # CONFIG_NET_VENDOR_RACAL is not set
 # CONFIG_RTL8139 is not set
 # CONFIG_YELLOWFIN is not set
+# CONFIG_ACENIC is not set
 # CONFIG_NET_ISA is not set
 CONFIG_NET_EISA=y
 CONFIG_PCNET32=m
@@ -239,10 +240,22 @@
 # Console drivers
 #
 CONFIG_DUMMY_CONSOLE=y
-# CONFIG_FB_OF is not set
+CONFIG_FB_OF=y
+# CONFIG_FB_CONTROL is not set
+# CONFIG_FB_PLATINUM is not set
+# CONFIG_FB_VALKYRIE is not set
+CONFIG_FB_ATY=y
+CONFIG_FB_IMSTT=y
+# CONFIG_FB_CT65550 is not set
+# CONFIG_FB_S3TRIO is not set
 # CONFIG_FB_MATROX is not set
+CONFIG_FB_ATY=y
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FBCON_ADVANCED is not set
+CONFIG_FBCON_CFB8=y
+CONFIG_FBCON_CFB16=y
+CONFIG_FBCON_CFB24=y
+CONFIG_FBCON_CFB32=y
 # CONFIG_FBCON_FONTWIDTH8_ONLY is not set
 # CONFIG_FBCON_FONTS is not set
 CONFIG_FONT_8x8=y
@@ -290,12 +303,13 @@
 # CONFIG_VFAT_FS is not set
 CONFIG_PROC_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFSD=y
+CONFIG_NFSD=m
 # CONFIG_NFSD_SUN is not set
 CONFIG_SUNRPC=y
 CONFIG_LOCKD=y
 # CONFIG_CODA_FS is not set
 # CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
 # CONFIG_HPFS_FS is not set
 # CONFIG_NTFS_FS is not set
 # CONFIG_SYSV_FS is not set
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/Makefile linux/arch/ppc/kernel/Makefile
--- v2.1.131/linux/arch/ppc/kernel/Makefile	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/Makefile	Mon Dec 21 08:37:20 1998
@@ -15,8 +15,7 @@
 
 
 O_OBJS := traps.o irq.o idle.o time.o process.o signal.o syscalls.o misc.o \
-	  bitops.o ptrace.o align.o ppc_htab.o feature.o
-
+	  bitops.o ptrace.o align.o ppc_htab.o
 ifdef CONFIG_PCI
 O_OBJS += pci.o
 endif
@@ -33,11 +32,13 @@
 ifeq ($(CONFIG_APUS),y)
 O_OBJS += apus_setup.o prom.o openpic.o
 else
+ifneq ($(CONFIG_MBX),y)
 O_OBJS += prep_time.o pmac_time.o chrp_time.o \
 	  pmac_setup.o pmac_support.o \
 	  prep_pci.o pmac_pci.o chrp_pci.o \
-	  residual.o prom.o openpic.o
+	  residual.o prom.o openpic.o feature.o
 OX_OBJS += chrp_setup.o prep_setup.o
+endif
 endif
 endif
 
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/apus_setup.c linux/arch/ppc/kernel/apus_setup.c
--- v2.1.131/linux/arch/ppc/kernel/apus_setup.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/apus_setup.c	Mon Dec 21 08:37:20 1998
@@ -329,9 +329,9 @@
 		int i;
 
 		for (i = 0; i < kmap_chunk_count;){
-			unsigned long virt = kmap_chunks[i++];
-			unsigned long size = kmap_chunks[i++];
 			unsigned long phys = kmap_chunks[i++];
+			unsigned long size = kmap_chunks[i++];
+			unsigned long virt = kmap_chunks[i++];
 			if (paddr >= phys
 			    && paddr < (phys + size)){
 				ret = virt + paddr - phys;
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/head.S linux/arch/ppc/kernel/head.S
--- v2.1.131/linux/arch/ppc/kernel/head.S	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/head.S	Mon Dec 21 08:37:20 1998
@@ -1,7 +1,7 @@
 /*
  *  arch/ppc/kernel/head.S
  *
- *  $Id: head.S,v 1.111 1998/11/10 01:10:32 paulus Exp $
+ *  $Id: head.S,v 1.113 1998/12/02 18:41:00 cort Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -148,6 +148,10 @@
  *  r4: virtual address of boot_infos_t
  *  r5: 0
  *
+ * APUS
+ *   r3: 'APUS'
+ *   Linux/m68k style BootInfo structure at &_end.
+ *
  * PREP
  * This is jumped to on prep systems right after the kernel is relocated
  * to its proper place in memory by the boot loader.  The expected layout
@@ -1204,9 +1208,23 @@
 Hash_base = 0x180000
 Hash_bits = 12				/* e.g. 256kB hash table */
 Hash_msk = (((1 << Hash_bits) - 1) * 64)
-
+	
+	.globl	hash_table_lock
+hash_table_lock:
+.long	0
+	
 	.globl	hash_page
 hash_page:
+#ifdef __SMP__
+	lis	r2,hash_table_lock@h
+	ori	r2,r2,hash_table_lock@l
+	tophys(r2,r2,r6)
+10:	lwarx	r6,0,r2
+	stwcx.	r2,0,r2
+	bne-	10b
+	cmpi	0,0,r6,0
+	bne	10b
+#endif
 	/* Get PTE (linux-style) and check access */
 	lwz	r5,PG_TABLES(r5)		
 	tophys(r5,r5,r2)		/* convert to phys addr */
@@ -1379,6 +1397,13 @@
 	mtcrf	0xff,r3
 	mtlr	r4
 	mtctr	r5
+#ifdef __SMP__
+	lis	r2,hash_table_lock@h
+	ori	r2,r2,hash_table_lock@l
+	tophys(r2,r2,r6)
+	li	r6,0
+	stw	r6,0(r2)
+#endif		
 	REST_GPR(0, r21)
 	REST_2GPRS(1, r21)
 	REST_4GPRS(3, r21)
@@ -1392,6 +1417,13 @@
 	rfi
 	
 hash_page_out:
+#ifdef __SMP__
+	lis	r2,hash_table_lock@h
+	ori	r2,r2,hash_table_lock@l
+	tophys(r2,r2,r6)
+	li	r6,0
+	stw	r6,0(r2)
+#endif		
 	blr
 next_slot:
 	.long	0
@@ -2195,6 +2227,15 @@
  */
 #ifndef CONFIG_8xx	
 _GLOBAL(flush_hash_segments)
+#ifdef __SMP__
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+10:	lwarx	r6,0,r9
+	stwcx.	r9,0,r9
+	bne-	10b
+	cmpi	0,0,r6,0
+	bne	10b
+#endif
 #ifdef NO_RELOAD_HTAB
 /*
  * Bitmask of PVR numbers of 603-like chips,
@@ -2231,6 +2272,12 @@
 	sync
 99:	tlbia
 	isync
+#ifdef __SMP__
+	lis	r3,hash_table_lock@h
+	ori	r3,r3,hash_table_lock@l
+	li	r6,0
+	stw	r6,0(r3)
+#endif		
 	blr
 
 /*
@@ -2239,6 +2286,15 @@
  * flush_hash_page(unsigned context, unsigned long va)
  */
 _GLOBAL(flush_hash_page)
+#ifdef __SMP__
+	lis	r9,hash_table_lock@h
+	ori	r9,r9,hash_table_lock@l
+10:	lwarx	r6,0,r9
+	stwcx.	r9,0,r9
+	bne-	10b
+	cmpi	0,0,r6,0
+	bne	10b
+#endif
 #ifdef NO_RELOAD_HTAB
 	mfspr	r0,PVR
 	rlwinm	r0,r0,16,27,31
@@ -2280,6 +2336,12 @@
 4:	sync
 99:	tlbie	r4			/* in hw tlb too */
 	isync
+#ifdef __SMP__
+	lis	r3,hash_table_lock@h
+	ori	r3,r3,hash_table_lock@l
+	li	r6,0
+	stw	r6,0(r3)
+#endif		
 	blr
 #endif /* CONFIG_8xx */
 /*
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.1.131/linux/arch/ppc/kernel/irq.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/irq.c	Mon Dec 21 08:37:20 1998
@@ -1,4 +1,6 @@
 /*
+ * $Id: irq.c,v 1.90 1998/12/10 02:39:46 cort Exp $
+ *
  *  arch/ppc/kernel/irq.c
  *
  *  Derived from arch/i386/kernel/irq.c
@@ -6,6 +8,7 @@
  *  Adapted from arch/i386 by Gary Thomas
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
  *  Updated and modified by Cort Dougan (cort@cs.nmt.edu)
+ *    Copyright (C) 1996 Cort Dougan
  *  Adapted for Power Macintosh by Paul Mackerras
  *    Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au)
  *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk).
@@ -309,14 +312,14 @@
 static void mbx_mask_irq(unsigned int irq_nr)
 {
 	cached_irq_mask[0] &= ~(1 << (31-irq_nr));
-	((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask =
+	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
 							cached_irq_mask[0];
 }
 
 static void mbx_unmask_irq(unsigned int irq_nr)
 {
 	cached_irq_mask[0] |= (1 << (31-irq_nr));
-	((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_simask =
+	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask =
 							cached_irq_mask[0];
 }
 #endif /* CONFIG_8xx */
@@ -799,9 +802,13 @@
 	}
 
 	if (irq < 0) {
-		printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
-		       irq, regs->nip);
-		spurious_interrupts++;
+		/* we get here with Gatwick but the 'bogus' isn't correct in that case -- Cort */
+		if ( irq != second_irq )
+		{
+			printk(KERN_DEBUG "Bogus interrupt %d from PC = %lx\n",
+			       irq, regs->nip);
+			spurious_interrupts++;
+		}
 		goto out;
 	}					
 	
@@ -809,7 +816,7 @@
 	/* For MPC8xx, read the SIVEC register and shift the bits down
 	 * to get the irq number.
 	 */
-	bits = ((immap_t *)MBX_IMAP_ADDR)->im_siu_conf.sc_sivec;
+	bits = ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec;
 	irq = bits >> 26;
 #endif /* CONFIG_8xx */
 	mask_and_ack_irq(irq);
@@ -1089,17 +1096,6 @@
 			 */
 			if ( _prep_type == _PREP_IBM )
 				irq_mode2 |= 0xa0;
-			/*
-			 * Sound on the Powerstack reportedly needs to be edge triggered
-			 */
-			if ( _prep_type == _PREP_Motorola )
-			{
-				irq_mode2 &= ~0x04L;
-				irq_mode2 = 0xca;
-				outb( irq_mode1 , 0x4d0 );
-				outb( irq_mode2 , 0x4d1 );
-			}
-
 		}
 		break;
 #ifdef CONFIG_APUS		
@@ -1116,8 +1112,7 @@
 /* This routine will fix some missing interrupt values in the device tree
  * on the gatwick mac-io controller used by some PowerBooks
  */
-__pmac
-static void pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
+static void __init pmac_fix_gatwick_interrupts(struct device_node *gw, int irq_base)
 {
 	struct device_node *node;
 	static struct interrupt_info int_pool[4];
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/mbx_setup.c linux/arch/ppc/kernel/mbx_setup.c
--- v2.1.131/linux/arch/ppc/kernel/mbx_setup.c	Fri May  8 23:14:44 1998
+++ linux/arch/ppc/kernel/mbx_setup.c	Mon Dec 21 08:37:20 1998
@@ -1,4 +1,6 @@
 /*
+ * $Id: mbx_setup.c,v 1.4 1998/11/15 19:58:55 cort Exp $
+ *
  *  linux/arch/ppc/kernel/setup.c
  *
  *  Copyright (C) 1995  Linus Torvalds
@@ -51,10 +53,17 @@
 extern char saved_command_line[256];
 
 extern unsigned long find_available_memory(void);
-extern void mbx_cpm_reset(uint);
+extern void m8xx_cpm_reset(uint);
 
+/* this really does make things cleaner -- Cort */
+void __init powermac_init(void)
+{
+}
+void __init adbdev_init(void)
+{
+}
 
-void mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
+void __init mbx_ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq)
 {
 
 	*p = 0;
@@ -88,7 +97,7 @@
 
 	/* Reset the Communication Processor Module.
 	*/
-	mbx_cpm_reset(cpm_page);
+	m8xx_cpm_reset(cpm_page);
 
 #ifdef notdef
 	ROOT_DEV = to_kdev_t(0x0301); /* hda1 */
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S
--- v2.1.131/linux/arch/ppc/kernel/misc.S	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/misc.S	Mon Dec 21 08:37:20 1998
@@ -383,6 +383,177 @@
 	mtspr	THRM3,r3
 	blr
 	
+_GLOBAL(_get_PVR)
+	mfspr	r3,PVR
+	blr
+/*
+	L2CR functions
+	Copyright © 1997-1998 by PowerLogix R & D, 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 distributed in the hope that it will be useful,
+	but WITHOUT ANY WARRANTY; without even the implied warranty of
+	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+	GNU General Public License for more details.
+	
+	You should have received a copy of the GNU General Public License
+	along with this program; if not, write to the Free Software
+	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+/*
+	Thur, Dec. 12, 1998.
+	- First public release, contributed by PowerLogix.
+	
+	Author:	Terry Greeniaus (tgree@phys.ualberta.ca)
+	Please e-mail updates to this file to me, thanks!
+*/
+
+_GLOBAL(_set_L2CR)
+	/* Usage:
+	
+		When setting the L2CR register, you must do a few special things.  If you are enabling the
+		cache, you must perform a global invalidate.  If you are disabling the cache, you must
+		flush the cache contents first.  This routine takes care of doing these things.  When first
+		enabling the cache, make sure you pass in the L2CR you want, as well as passing in the
+		global invalidate bit set.  A global invalidate will only be performed if the L2I bit is set
+		in applyThis.  When enabling the cache, you should also set the L2E bit in applyThis.  If you
+		want to modify the L2CR contents after the cache has been enabled, the recommended
+		procedure is to first call __setL2CR(0) to disable the cache and then call it again with
+		the new values for L2CR.  Examples:
+	
+			_setL2CR(0)			-	disables the cache
+			_setL2CR(0xB3A04000)		-	enables my G3 upgrade card:
+							-	L2E set to turn on the cache
+							-	L2SIZ set to 1MB
+							-	L2CLK set to 1:1
+							-	L2RAM set to pipelined syncronous late-write
+							-	L2I set to perform a global invalidation
+							-	L2OH set to 0.5 nS
+							-	L2DF set because this upgrade card requires it
+	
+		A similar call should work for your card.  You need to know the correct setting for your
+		card and then place them in the fields I have outlined above.  Other fields support optional
+		features, such as L2DO which caches only data, or L2TS which causes cache pushes from
+		the L1 cache to go to the L2 cache instead of to main memory.
+	*/
+	
+	/* Make sure this is a 750 chip */
+	mfspr	r4,PVR
+	rlwinm	r4,r4,16,16,31
+	cmplwi	r4,0x0008
+	beq	thisIs750
+	li	r3,-1
+	blr
+	
+thisIs750:
+	/* Get the current enable bit of the L2CR into r4 */
+	mfspr	r4,L2CR
+	rlwinm	r4,r4,0,0,0
+	
+	/* See if we want to perform a global inval this time. */
+	rlwinm	r6,r3,0,10,10		/* r6 contains the new invalidate bit */
+	rlwinm.	r5,r3,0,0,0		/* r5 contains the new enable bit */
+	rlwinm	r3,r3,0,11,9		/* Turn off the invalidate bit */
+	rlwinm	r3,r3,0,1,31		/* Turn off the enable bit */
+	or	r3,r3,r4		/* Keep the enable bit the same as it was for now. */
+	bne	dontDisableCache	/* Only disable the cache if L2CRApply has the enable bit off */
+
+disableCache:
+	/* Disable the cache.  First, we turn off data relocation. */
+	mfmsr	r7
+	rlwinm	r4,r7,0,28,26		/* Turn off DR bit */
+	rlwinm	r4,r4,0,17,15		/* Turn off EE bit - an external exception while we are flushing
+					   the cache is fatal (comment this line and see!) */
+	sync
+	mtmsr	r4
+	sync
+	
+	/*
+		Now, read the first 2MB of memory to put new data in the cache.
+		(Actually we only need the size of the L2 cache plus
+		the size of the L1 cache, but 2MB will cover everything just to be safe).
+	*/
+	lis	r4,0x0001
+	mtctr	r4
+	li	r4,0
+loadLoop:
+	lwzx	r0,r0,r4
+	addi	r4,r4,0x0020		/* Go to start of next cache line */
+	bdnz	loadLoop
+	
+	/* Now, flush the first 2MB of memory */
+	lis	r4,0x0001
+	mtctr	r4
+	li	r4,0
+	sync
+flushLoop:
+	dcbf	r0,r4
+	addi	r4,r4,0x0020	/* Go to start of next cache line */
+	bdnz	flushLoop
+	
+	/* Turn off the L2CR enable bit. */
+	rlwinm	r3,r3,0,1,31
+	
+	/* Reenable data relocation. */
+	sync
+	mtmsr	r7
+	sync
+	
+dontDisableCache:
+	/* Set up the L2CR configuration bits */
+	sync
+	mtspr	L2CR,r3
+	sync
+	cmplwi	r6,0
+	beq	noInval
+	
+	/* Perform a global invalidation */
+	oris	r3,r3,0x0020
+	sync
+	mtspr	1017,r3
+	sync
+invalCompleteLoop:			/* Wait for the invalidation to complete */
+	mfspr	r3,1017
+	rlwinm.	r4,r3,0,31,31
+	bne	invalCompleteLoop
+	
+	rlwinm	r3,r3,0,11,9;		/* Turn off the L2I bit */
+	sync
+	mtspr	L2CR,r3
+	sync
+	
+noInval:
+	/* See if we need to enable the cache */
+	cmplwi	r5,0
+	beqlr
+	
+enableCache:
+	/* Enable the cache */
+	oris	r3,r3,0x8000
+	mtspr	L2CR,r3
+	sync
+	blr
+
+_GLOBAL(_get_L2CR)
+	/* Make sure this is a 750 chip */
+	mfspr	r3,PVR
+	rlwinm	r3,r3,16,16,31
+	cmplwi	r3,0x0008
+	li	r3,0
+	bnelr
+	
+	/* Return the L2CR contents */
+	mfspr	r3,L2CR
+	blr
+
+/* --- End of PowerLogix code ---
+ */
+
+/*
 _GLOBAL(_get_L2CR)
 	mfspr	r3,L2CR
 	blr
@@ -391,9 +562,7 @@
 	mtspr	L2CR,r3
 	blr
 		
-_GLOBAL(_get_PVR)
-	mfspr	r3,PVR
-	blr
+*/
 
 /*
  * These are used in the alignment trap handler when emulating
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
--- v2.1.131/linux/arch/ppc/kernel/pci.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/pci.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: pci.c,v 1.39 1998/10/13 20:59:04 cort Exp $
+ * $Id: pci.c,v 1.42 1998/12/04 14:31:37 cort Exp $
  * Common pmac/prep/chrp pci routines. -- Cort
  */
 
@@ -188,13 +188,7 @@
 	extern struct bridge_data **bridges;
 	extern unsigned char *Motherboard_map;
 	extern unsigned char *Motherboard_routes;
-	
-	/*
-	 * FIXME: This is broken: We should not assign IRQ's to IRQless
-	 *	  devices (look at PCI_INTERRUPT_PIN) and we also should
-	 *	  honor the existence of multi-function devices where
-	 *	  different functions have different interrupt pins. [mj]
-	 */
+#ifndef CONFIG_MBX
 	switch (_machine )
 	{
 	case _MACH_prep:
@@ -206,8 +200,23 @@
 			 * irq this device uses.  This is necessary on things
 			 * without residual data. -- Cort
 			 */
-			unsigned char d = PCI_SLOT(dev->devfn);
+			unsigned char d = PCI_SLOT(dev->devfn), i;
 			dev->irq = Motherboard_routes[Motherboard_map[d]];
+			for ( i = 0 ; i <= 5 ; i++ )
+			{
+				if ( dev->base_address[i] > 0x10000000 )
+				{
+					printk("Relocating PCI address %x -> %x\n",
+					       dev->base_address[i],
+					       (dev->base_address[i] & 0x00FFFFFF)
+				               | 0x01000000);
+					dev->base_address[i] =
+					  (dev->base_address[i] & 0x00FFFFFF) | 0x01000000;
+					pci_write_config_dword(dev,
+						PCI_BASE_ADDRESS_0+(i*0x4),
+						dev->base_address[i] );
+				}
+			}
 #if 0			
 			/*
 			 * If we have residual data and if it knows about this
@@ -255,6 +264,11 @@
 		}
 		break;
 	}
+#else /* CONFIG_MBX */
+	for(dev=pci_devices; dev; dev=dev->next)
+	{
+	}
+#endif /* CONFIG_MBX */
 }
 
 __initfunc(void pcibios_fixup_bus(struct pci_bus *bus))
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/ppc_htab.c linux/arch/ppc/kernel/ppc_htab.c
--- v2.1.131/linux/arch/ppc/kernel/ppc_htab.c	Mon Oct  5 13:13:36 1998
+++ linux/arch/ppc/kernel/ppc_htab.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: ppc_htab.c,v 1.25 1998/08/26 10:28:26 davem Exp $
+ * $Id: ppc_htab.c,v 1.26 1998/12/10 00:24:23 cort Exp $
  *
  * PowerPC hash table management proc entry.  Will show information
  * about the current hash table and will allow changes to it.
@@ -569,6 +569,7 @@
 				break;
 			buffer += len;
 			left -= len;
+			_set_L2CR(0);
 			_set_L2CR(val);
 			while ( _get_L2CR() & 0x1 )
 				/* wait for invalidate to finish */;
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.1.131/linux/arch/ppc/kernel/ppc_ksyms.c	Fri Nov 27 13:09:22 1998
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Mon Dec 21 08:37:20 1998
@@ -185,7 +185,9 @@
 EXPORT_SYMBOL(feature_set);
 EXPORT_SYMBOL(feature_clear);
 EXPORT_SYMBOL(feature_test);
+#ifdef CONFIG_SCSI
 EXPORT_SYMBOL(note_scsi_host);
+#endif
 EXPORT_SYMBOL(kd_mksound);
 #ifdef CONFIG_PMAC
 EXPORT_SYMBOL(nvram_read_byte);
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/prep_pci.c linux/arch/ppc/kernel/prep_pci.c
--- v2.1.131/linux/arch/ppc/kernel/prep_pci.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/prep_pci.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: prep_pci.c,v 1.23 1998/10/21 10:52:24 cort Exp $
+ * $Id: prep_pci.c,v 1.24 1998/12/10 02:39:51 cort Exp $
  * PReP pci functions.
  * Originally by Gary Thomas
  * rewritten and updated by Cort Dougan (cort@cs.nmt.edu)
@@ -107,7 +107,7 @@
 };
 
 /* Motorola PowerStack */
-static char Blackhawk_pci_IRQ_map[16] __prepdata =
+static char Blackhawk_pci_IRQ_map[19] __prepdata =
 {
   	0,	/* Slot 0  - unused */
   	0,	/* Slot 1  - unused */
@@ -125,6 +125,9 @@
   	0,	/* Slot 13 - unused */
   	1,	/* Slot 14 - Ethernet */
   	0,	/* Slot 15 - unused */
+  	1,	/* Slot P7 */
+  	2,	/* Slot P6 */
+  	3,	/* Slot P5 */
 };
 
 static char Blackhawk_pci_IRQ_routes[] __prepdata =
@@ -132,7 +135,7 @@
    	0,	/* Line 0 - Unused */
    	9,	/* Line 1 */
    	11,	/* Line 2 */
-   	14,	/* Line 3 */
+   	15,	/* Line 3 */
    	15	/* Line 4 */
 };
    
@@ -226,6 +229,7 @@
         0, /* Slot 21 - unused */
         2, /* Slot 22 - PCI slot 1 PCIINTx# (See below) */
 };
+
 static char ibm8xx_pci_IRQ_routes[] __prepdata = {
         0,      /* Line 0 - unused */
         13,     /* Line 1 */
@@ -440,6 +444,8 @@
 	
 	if ( _prep_type == _PREP_Motorola)
 	{
+		unsigned short irq_mode;
+
 		switch (inb(0x800) & 0xF0)
 		{
 		case 0x10: /* MVME16xx */
@@ -474,6 +480,14 @@
 			Motherboard_routes = Blackhawk_pci_IRQ_routes;
 			break;
 		}
+		/* AJF adjust level/edge control according to routes */
+		irq_mode = 0;
+		for (i = 1;  i <= 4;  i++)
+		{
+			irq_mode |= ( 1 << Motherboard_routes[i] );
+		}
+		outb( irq_mode & 0xff, 0x4d0 );
+		outb( (irq_mode >> 8) & 0xff, 0x4d1 );
 	} else if ( _prep_type == _PREP_IBM )
 	{
 		unsigned char pl_id;
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.1.131/linux/arch/ppc/kernel/prep_setup.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/prep_setup.c	Mon Dec 21 08:37:20 1998
@@ -189,11 +189,6 @@
 	/* Enable L2.  Assume we don't need to flush -- Cort*/
 	*(unsigned char *)(0x8000081c) = *(unsigned char *)(0x8000081c)|3;
 	
-	/* make the serial port the console */
-	/* strcat(cmd_line,"console=ttyS0,9600n8"); */
-	/* use the normal console but send output to the serial port, too */
-	/*strcat(cmd_line,"console=tty0 console=ttyS0,9600n8");*/
-        sprintf(cmd_line,"%s console=tty0 console=ttyS0,9600n8", cmd_line);
 	printk("Boot arguments: %s\n", cmd_line);
 	
 #ifdef CONFIG_SOUND_CS4232
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.1.131/linux/arch/ppc/kernel/process.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/process.c	Mon Dec 21 08:37:20 1998
@@ -1,4 +1,6 @@
 /*
+ * $Id: process.c,v 1.68 1998/11/15 19:59:02 cort Exp $
+ *
  *  linux/arch/ppc/kernel/process.c
  *
  *  Derived from "arch/i386/kernel/process.c"
@@ -450,6 +452,7 @@
 	printk("\n");
 }
 
+#if 0
 /*
  * Low level print for debugging - Cort
  */
@@ -537,3 +540,4 @@
 	orig_x = x;
 	orig_y = y;
 }
+#endif
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.1.131/linux/arch/ppc/kernel/setup.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/setup.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: setup.c,v 1.117 1998/11/09 19:55:53 geert Exp $
+ * $Id: setup.c,v 1.120 1998/12/10 00:24:28 cort Exp $
  * Common prep/pmac/chrp boot and setup code.
  */
 
@@ -35,7 +35,7 @@
 extern int parse_bootinfo(const struct bi_record *);
 extern char _end[];
 #ifdef CONFIG_APUS
-struct mem_info ramdisk;
+extern struct mem_info ramdisk;
 unsigned long isa_io_base;
 unsigned long isa_mem_base;
 unsigned long pci_dram_offset;
@@ -665,7 +665,7 @@
 #else /* CONFIG_MBX */
 
 	if ( r3 )
-		memcpy( (void *)&res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
+		memcpy( (void *)res,(void *)(r3+KERNELBASE), sizeof(bd_t) );
 	
 #ifdef CONFIG_PCI
 	setup_pci_ptrs();
@@ -693,7 +693,20 @@
 		extern int __map_without_bats;
 		__map_without_bats = 1;
 	}
+	
 	return 0;
+}
+
+/* Checks "l2cr=xxxx" command-line option */
+void ppc_setup_l2cr(char *str, int *ints)
+{
+	if ( (_get_PVR() >> 16) == 8)
+	{
+		unsigned long val = simple_strtoul(str, NULL, 0);
+		printk(KERN_INFO "l2cr set to %lx\n", val);
+		_set_L2CR(0);
+		_set_L2CR(val);
+	}
 }
 
 __initfunc(void setup_arch(char **cmdline_p,
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/smp.c linux/arch/ppc/kernel/smp.c
--- v2.1.131/linux/arch/ppc/kernel/smp.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/smp.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: smp.c,v 1.36 1998/10/08 01:17:48 cort Exp $
+ * $Id: smp.c,v 1.38 1998/12/02 21:23:49 cort Exp $
  *
  * Smp support for ppc.
  *
@@ -152,7 +152,7 @@
 {
 	if ( _machine != _MACH_Pmac )
 		return;
-	/*printk("SMP %d: sending smp message\n", current->processor);*/
+printk("SMP %d: sending smp message %x\n", current->processor, msg);
 if (smp_processor_id() ) printk("pass from cpu 1\n");
 	spin_lock(&mesg_pass_lock);
 #define OTHER (~smp_processor_id() & 1)
@@ -179,7 +179,7 @@
 	spin_unlock(&mesg_pass_lock);	
 }
 
-__initfunc(void smp_boot_cpus(void))
+void __init smp_boot_cpus(void)
 {
 	extern struct task_struct *current_set[NR_CPUS];
 	extern void __secondary_start(void);
@@ -251,19 +251,17 @@
 	smp_message_pass(1,0xf0f0, 0, 0);
 }
 
-__initfunc(void smp_commence(void))
+void __init smp_commence(void)
 {
 	printk("SMP %d: smp_commence()\n",current->processor);
 	/*
 	 *	Lets the callin's below out of their loop.
 	 */
-	local_flush_tlb_all();
 	smp_commenced = 1;
-	local_flush_tlb_all();
 }
 
 /* intel needs this */
-__initfunc(void initialize_secondary(void))
+void __init initialize_secondary(void)
 {
 }
 
@@ -275,33 +273,33 @@
 	return cpu_idle(NULL);
 }
 
-__initfunc(void smp_callin(void))
+void __init smp_callin(void)
 {
 	printk("SMP %d: smp_callin()\n",current->processor);
         smp_store_cpu_info(current->processor);
 	set_dec(decrementer_count);
-	
+#if 0
 	current->mm->mmap->vm_page_prot = PAGE_SHARED;
 	current->mm->mmap->vm_start = PAGE_OFFSET;
 	current->mm->mmap->vm_end = init_task.mm->mmap->vm_end;
-
-	cpu_callin_map[current->processor] = current->processor;
+#endif
+	cpu_callin_map[current->processor] = 1;
 	while(!smp_commenced)
 		barrier();
 	__sti();
 }
 
-__initfunc(void smp_setup(char *str, int *ints))
+void __init smp_setup(char *str, int *ints)
 {
 	printk("SMP %d: smp_setup()\n",current->processor);
 }
 
-__initfunc(int setup_profiling_timer(unsigned int multiplier))
+int __init setup_profiling_timer(unsigned int multiplier)
 {
 	return 0;
 }
 
-__initfunc(void smp_store_cpu_info(int id))
+void __init smp_store_cpu_info(int id)
 {
         struct cpuinfo_PPC *c = &cpu_data[id];
 
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.1.131/linux/arch/ppc/kernel/time.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/kernel/time.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- * $Id: time.c,v 1.36 1998/10/10 12:16:08 geert Exp $
+ * $Id: time.c,v 1.38 1998/11/16 15:56:15 cort Exp $
  * Common time routines among all ppc machines.
  *
  * Written by Cort Dougan (cort@cs.nmt.edu) to merge
@@ -133,9 +133,9 @@
 static int
 mbx_set_rtc_time(unsigned long time)
 {
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
-	((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc = time;
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
+	((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = KAPWR_KEY;
+	((immap_t *)IMAP_ADDR)->im_sit.sit_rtc = time;
+	((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtck = ~KAPWR_KEY;
 	return(0);
 }
 #endif /* CONFIG_MBX */
@@ -227,13 +227,13 @@
 	 * modify these registers we have to write the key value to
 	 * the key location associated with the register.
 	 */
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
-	((immap_t *)MBX_IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
+	((immap_t *)IMAP_ADDR)->im_sitk.sitk_tbscrk = KAPWR_KEY;
+	((immap_t *)IMAP_ADDR)->im_sitk.sitk_rtcsck = KAPWR_KEY;
 
 
 	/* Disable the RTC one second and alarm interrupts.
 	*/
-	((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtcsc &=
+	((immap_t *)IMAP_ADDR)->im_sit.sit_rtcsc &=
 						~(RTCSC_SIE | RTCSC_ALE);
 
 	/* Enabling the decrementer also enables the timebase interrupts
@@ -241,7 +241,7 @@
 	 * we have to enable the timebase).  The decrementer interrupt
 	 * is wired into the vector table, nothing to do here for that.
 	 */
-	((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_tbscr =
+	((immap_t *)IMAP_ADDR)->im_sit.sit_tbscr =
 				((mk_int_int_mask(DEC_INTERRUPT) << 8) |
 					 (TBSCR_TBF | TBSCR_TBE));
 	if (request_irq(DEC_INTERRUPT, timebase_interrupt, 0, "tbint", NULL) != 0)
@@ -249,7 +249,7 @@
 
 	/* Get time from the RTC.
 	*/
-	xtime.tv_sec = ((immap_t *)MBX_IMAP_ADDR)->im_sit.sit_rtc;
+	xtime.tv_sec = ((immap_t *)IMAP_ADDR)->im_sit.sit_rtc;
 	xtime.tv_usec = 0;
 
 #endif /* CONFIG_MBX */
@@ -343,10 +343,10 @@
  */
 __initfunc(void mbx_calibrate_decr(void))
 {
-	bd_t	*binfo = (bd_t *)&res;
+	bd_t	*binfo = (bd_t *)res;
 	int freq, fp, divisor;
 
-	if ((((immap_t *)MBX_IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
+	if ((((immap_t *)IMAP_ADDR)->im_clkrst.car_sccr & 0x02000000) == 0)
 		printk("WARNING: Wrong decrementer source clock.\n");
 
 	/* The manual says the frequency is in Hz, but it is really
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/mbx_defconfig linux/arch/ppc/mbx_defconfig
--- v2.1.131/linux/arch/ppc/mbx_defconfig	Sun Nov  8 14:02:44 1998
+++ linux/arch/ppc/mbx_defconfig	Mon Dec 21 08:37:20 1998
@@ -14,15 +14,16 @@
 # CONFIG_ALL_PPC is not set
 # CONFIG_APUS is not set
 CONFIG_MBX=y
-CONFIG_SERIAL_CONSOLE=y
 CONFIG_MACH_SPECIFIC=y
+CONFIG_SERIAL_CONSOLE=y
 
 #
 # General setup
 #
-# CONFIG_EXPERIMENTAL is not set
+CONFIG_EXPERIMENTAL=y
 # CONFIG_MODULES is not set
 CONFIG_PCI=y
+# CONFIG_PCI_QUIRKS is not set
 CONFIG_PCI_OLD_PROC=y
 CONFIG_NET=y
 # CONFIG_SYSCTL is not set
@@ -33,13 +34,19 @@
 # CONFIG_BINFMT_MISC is not set
 # CONFIG_BINFMT_JAVA is not set
 # CONFIG_PARPORT is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_FB is not set
+# CONFIG_PMAC_PBOOK is not set
 # CONFIG_MAC_KEYBOARD is not set
 # CONFIG_MAC_FLOPPY is not set
 # CONFIG_MAC_SERIAL is not set
+# CONFIG_ADBMOUSE is not set
+# CONFIG_BLK_DEV_IDE_PMAC is not set
 # CONFIG_PROC_DEVICETREE is not set
 # CONFIG_KGDB is not set
 # CONFIG_XMON is not set
-CONFIG_VGA_CONSOLE=y
+# CONFIG_TOTALMP is not set
+# CONFIG_BOOTX_TEXT is not set
 
 #
 # Plug and Play support
@@ -47,7 +54,7 @@
 # CONFIG_PNP is not set
 
 #
-# Floppy, IDE, and other block devices
+# Block devices
 #
 # CONFIG_BLK_DEV_FD is not set
 # CONFIG_BLK_DEV_IDE is not set
@@ -84,8 +91,19 @@
 # CONFIG_INET_RARP is not set
 CONFIG_IP_NOSR=y
 # CONFIG_SKB_LARGE is not set
+# CONFIG_IPV6 is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+# CONFIG_CPU_IS_SLOW is not set
+# CONFIG_NET_SCHED is not set
 
 #
 # SCSI support
@@ -100,22 +118,26 @@
 # CONFIG_DUMMY is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_NET_ETHERNET=y
+# CONFIG_MACE is not set
+# CONFIG_BMAC is not set
 # CONFIG_NET_VENDOR_3COM is not set
 # CONFIG_LANCE is not set
 # CONFIG_NET_VENDOR_SMC is not set
 # CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_RTL8139 is not set
+# CONFIG_YELLOWFIN is not set
 # CONFIG_NET_ISA is not set
 # CONFIG_NET_EISA is not set
 # CONFIG_NET_POCKET is not set
 # CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
 # CONFIG_DLCI is not set
 # CONFIG_PPP is not set
 # CONFIG_SLIP is not set
 # CONFIG_NET_RADIO is not set
 # CONFIG_TR is not set
-# CONFIG_WAN_DRIVERS is not set
-# CONFIG_LAPBETHER is not set
-# CONFIG_X25_ASY is not set
+# CONFIG_SHAPER is not set
+# CONFIG_HOSTESS_SV11 is not set
 
 #
 # Amateur Radio support
@@ -133,6 +155,32 @@
 # CONFIG_CD_NO_IDESCSI is not set
 
 #
+# Console drivers
+#
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_SERIAL=y
+CONFIG_SERIAL_CONSOLE=y
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_MOUSE is not set
+# CONFIG_QIC02_TAPE is not set
+# CONFIG_WATCHDOG is not set
+# CONFIG_RTC is not set
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_NVRAM is not set
+# CONFIG_JOYSTICK is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+
+#
 # Filesystems
 #
 # CONFIG_QUOTA is not set
@@ -159,29 +207,13 @@
 # CONFIG_ROMFS_FS is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_SMD_DISKLABEL is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
 # CONFIG_MAC_PARTITION is not set
 # CONFIG_NLS is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-# CONFIG_SERIAL is not set
-# CONFIG_SERIAL_EXTENDED is not set
-# CONFIG_SERIAL_NONSTANDARD is not set
-# CONFIG_MOUSE is not set
-# CONFIG_QIC02_TAPE is not set
-# CONFIG_WATCHDOG is not set
-# CONFIG_RTC is not set
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_NVRAM is not set
-# CONFIG_JOYSTICK is not set
-# CONFIG_MISC_RADIO is not set
-
-#
-# Ftape, the floppy tape device driver
-#
-# CONFIG_FTAPE is not set
 
 #
 # Sound
diff -u --recursive --new-file v2.1.131/linux/arch/ppc/mm/init.c linux/arch/ppc/mm/init.c
--- v2.1.131/linux/arch/ppc/mm/init.c	Thu Nov 19 09:56:27 1998
+++ linux/arch/ppc/mm/init.c	Mon Dec 21 08:37:20 1998
@@ -1,5 +1,5 @@
 /*
- *  $Id: init.c,v 1.130 1998/11/10 10:09:20 paulus Exp $
+ *  $Id: init.c,v 1.138 1998/12/15 17:34:43 cort Exp $
  *
  *  PowerPC version 
  *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
@@ -55,7 +55,7 @@
 /* END APUS includes */
 
 int prom_trashed;
-int next_mmu_context;
+atomic_t next_mmu_context;
 unsigned long *end_of_DRAM;
 int mem_init_done;
 extern pgd_t swapper_pg_dir[];
@@ -71,7 +71,8 @@
 unsigned long ioremap_bot;
 unsigned long avail_start;
 struct pgtable_cache_struct quicklists;
-struct mem_info memory[NUM_MEMINFO];
+extern int num_memory;
+extern struct mem_info memory[NUM_MEMINFO];
 extern boot_infos_t *boot_infos;
 
 void MMU_init(void);
@@ -89,6 +90,27 @@
 extern void die_if_kernel(char *,struct pt_regs *,long);
 extern void show_net_buffers(void);
 
+
+/*
+ * The following stuff defines a data structure for representing
+ * areas of memory as an array of (address, length) pairs, and
+ * procedures for manipulating them.
+ */
+#define MAX_MEM_REGIONS	32
+
+struct mem_pieces {
+	int n_regions;
+	struct reg_property regions[MAX_MEM_REGIONS];
+};
+struct mem_pieces phys_mem;
+struct mem_pieces phys_avail;
+struct mem_pieces prom_mem;
+
+static void remove_mem_piece(struct mem_pieces *, unsigned, unsigned, int);
+void *find_mem_piece(unsigned, unsigned);
+static void print_mem_pieces(struct mem_pieces *);
+static void append_mem_piece(struct mem_pieces *, unsigned, unsigned);
+
 extern struct task_struct *current_set[NR_CPUS];
 
 PTE *Hash, *Hash_end;
@@ -529,38 +551,19 @@
 	}
 	read_unlock(&tasklist_lock);
 	flush_hash_segments(0x10, 0xffffff);
-	next_mmu_context = 0;
+	atomic_set(&next_mmu_context, 0);
 	/* make sure current always has a context */
-	current->mm->context = MUNGE_CONTEXT(++next_mmu_context);
+	current->mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));
 	set_context(current->mm->context);
 #else
 	/* We set the value to -1 because it is pre-incremented before
 	 * before use.
 	 */
-	next_mmu_context = -1;
+	atomic_set(&next_mmu_context, -1);
 #endif
 }
 
 /*
- * The following stuff defines a data structure for representing
- * areas of memory as an array of (address, length) pairs, and
- * procedures for manipulating them.
- */
-#define MAX_MEM_REGIONS	32
-
-struct mem_pieces {
-	int n_regions;
-	struct reg_property regions[MAX_MEM_REGIONS];
-};
-struct mem_pieces phys_mem;
-struct mem_pieces phys_avail;
-struct mem_pieces prom_mem;
-
-static void remove_mem_piece(struct mem_pieces *, unsigned, unsigned, int);
-void *find_mem_piece(unsigned, unsigned);
-static void print_mem_pieces(struct mem_pieces *);
-
-/*
  * Scan a region for a piece of a given size with the required alignment.
  */
 __initfunc(void *
@@ -653,14 +656,26 @@
 	printk("\n");
 }
 
+/*
+ * Add some memory to an array of pieces
+ */
+__initfunc(static void
+	   append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size))
+{
+	struct reg_property *rp;
 
+	if (mp->n_regions >= MAX_MEM_REGIONS)
+		return;
+	rp = &mp->regions[mp->n_regions++];
+	rp->address = start;
+	rp->size = size;
+}
 
 #ifndef CONFIG_8xx
 static void hash_init(void);
 static void get_mem_prop(char *, struct mem_pieces *);
 static void sort_mem_pieces(struct mem_pieces *);
 static void coalesce_mem_pieces(struct mem_pieces *);
-static void append_mem_piece(struct mem_pieces *, unsigned, unsigned);
 
 __initfunc(static void sort_mem_pieces(struct mem_pieces *mp))
 {
@@ -703,21 +718,6 @@
 }
 
 /*
- * Add some memory to an array of pieces
- */
-__initfunc(static void
-	   append_mem_piece(struct mem_pieces *mp, unsigned start, unsigned size))
-{
-	struct reg_property *rp;
-
-	if (mp->n_regions >= MAX_MEM_REGIONS)
-		return;
-	rp = &mp->regions[mp->n_regions++];
-	rp->address = start;
-	rp->size = size;
-}
-
-/*
  * Read in a property describing some pieces of memory.
  */
 
@@ -963,8 +963,10 @@
 #ifndef CONFIG_8xx
 	if (have_of)
 		end_of_DRAM = pmac_find_end_of_memory();
+#ifdef CONFIG_APUS
 	else if (_machine == _MACH_apus )
 		end_of_DRAM = apus_find_end_of_memory();
+#endif
 	else /* prep */
 		end_of_DRAM = prep_find_end_of_memory();
 
@@ -1023,7 +1025,7 @@
          */
         ioremap(NVRAM_ADDR, NVRAM_SIZE);
         ioremap(MBX_CSR_ADDR, MBX_CSR_SIZE);
-        ioremap(MBX_IMAP_ADDR, MBX_IMAP_SIZE);
+        ioremap(IMAP_ADDR, IMAP_SIZE);
         ioremap(PCI_CSR_ADDR, PCI_CSR_SIZE);
 #endif /* CONFIG_8xx */
 }
@@ -1189,7 +1191,7 @@
 	volatile memctl8xx_t	*mcp;
 	unsigned long *ret;
 	
-	binfo = (bd_t *)&res;
+	binfo = (bd_t *)res;
 
 	/*
 	 * The MBX does weird things with the mmaps for ram.
@@ -1200,11 +1202,13 @@
 	 * In fact, it might be the best idea to just read the DRAM
 	 * config registers and set the mem areas accordingly.
 	 */
-	mcp = (memctl8xx_t *)(&(((immap_t *)MBX_IMAP_ADDR)->im_memctl));
+	mcp = (memctl8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_memctl));
+	append_mem_piece(&phys_mem, 0, binfo->bi_memsize);
+#if 0
 	phys_mem.regions[0].address = 0;
-	phys_mem.regions[0].size = binfo->bi_memsize;
-	
+	phys_mem.regions[0].size = binfo->bi_memsize;	
 	phys_mem.n_regions = 1;
+#endif	
 	
 	ret = __va(phys_mem.regions[0].address+
 		   phys_mem.regions[0].size);
@@ -1322,6 +1326,7 @@
 	return (__va(total));
 }
 
+#ifdef CONFIG_APUS
 #define HARDWARE_MAPPED_SIZE (512*1024)
 __initfunc(unsigned long *apus_find_end_of_memory(void))
 {
@@ -1381,15 +1386,22 @@
 		/* Remove the upper 512KB where the PPC exception
                    vectors are mapped. */
 		top -= HARDWARE_MAPPED_SIZE;
-		remove_mem_piece(&phys_avail, top,
-				 HARDWARE_MAPPED_SIZE, 0);
+#if 0
+		/* This would be neat, but it breaks on A3000 machines!? */
+		remove_mem_piece(&phys_avail, top, 16384, 0);
+#else
+		remove_mem_piece(&phys_avail, top, HARDWARE_MAPPED_SIZE, 0);
+#endif
+
 	}
 
-	/* FIXME:APUS: Only handles one block of memory! Problem is
-	   that the VTOP/PTOV code in head.S would be a mess if it had
-	   to handle more than one block.  */
+	/* Linux/APUS only handles one block of memory -- the one on
+	   the PowerUP board. Other system memory is horrible slow in
+	   comparison. The user can use other memory for swapping
+	   using the z2ram device. */
 	return __va(memory[0].addr + memory[0].size);
 }
+#endif /* CONFIG_APUS */
 
 /*
  * Initialize the hash table and patch the instructions in head.S.
@@ -1400,7 +1412,7 @@
 	unsigned long h, ramsize;
 
 	extern unsigned int hash_page_patch_A[], hash_page_patch_B[],
-		hash_page_patch_C[];
+		hash_page_patch_C[], hash_page[];
 
 	/*
 	 * Allow 64k of hash table for every 16MB of memory,
@@ -1475,7 +1487,17 @@
 		flush_icache_range((unsigned long) b(hash_page_patch_A),
 				   (unsigned long) b(hash_page_patch_C + 1));
 	}
-	else
+	else {
 		Hash_end = 0;
+		/*
+		 * Put a blr (procedure return) instruction at the
+		 * start of hash_page, since we can still get DSI
+		 * exceptions on a 603.
+		 */
+		*b(hash_page) = 0x4e800020;
+		flush_icache_range((unsigned long) b(hash_page),
+				   (unsigned long) b(hash_page + 1));
+	}
 }
 #endif /* ndef CONFIG_8xx */
+
diff -u --recursive --new-file v2.1.131/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.1.131/linux/arch/sparc/config.in	Mon Oct  5 13:13:37 1998
+++ linux/arch/sparc/config.in	Fri Dec 18 14:01:48 1998
@@ -25,6 +25,7 @@
 define_bool CONFIG_VT_CONSOLE y
 
 bool 'Support for AP1000 multicomputer' CONFIG_AP1000
+bool 'Symmetric multi-processing support' CONFIG_SMP
 
 if [ "$CONFIG_AP1000" = "y" ]; then
 	define_bool CONFIG_NO_KEYBOARD y
diff -u --recursive --new-file v2.1.131/linux/arch/sparc/defconfig linux/arch/sparc/defconfig
--- v2.1.131/linux/arch/sparc/defconfig	Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc/defconfig	Fri Dec 18 14:01:48 1998
@@ -20,6 +20,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_AP1000 is not set
+# CONFIG_SMP is not set
 # CONFIG_SUN4 is not set
 # CONFIG_PCI is not set
 
diff -u --recursive --new-file v2.1.131/linux/arch/sparc/kernel/Makefile linux/arch/sparc/kernel/Makefile
--- v2.1.131/linux/arch/sparc/kernel/Makefile	Mon Oct  5 13:13:37 1998
+++ linux/arch/sparc/kernel/Makefile	Fri Dec 18 14:01:48 1998
@@ -30,7 +30,7 @@
 O_OBJS += sun4setup.o
 endif
 
-ifdef SMP
+ifdef CONFIG_SMP
 O_OBJS += trampoline.o smp.o sun4m_smp.o sun4d_smp.o
 endif
 
@@ -50,11 +50,17 @@
 	@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
 	@echo "#define __ASM_OFFSETS_H__" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#ifndef __SMP__" >> asm_offsets.h
+	@echo "#include <linux/config.h>" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#include <linux/sched.h>" > tmp.c
+	@echo "#ifndef CONFIG_SMP" >> asm_offsets.h
+	@echo "" >> asm_offsets.h
+	@echo "#include <linux/config.h>" > tmp.c
+	@echo "#undef CONFIG_SMP" >> tmp.c
+	@echo "#include <linux/sched.h>" >> tmp.c
 	$(CC) -E tmp.c -o tmp.i
 	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
+	@echo "#include <linux/config.h>" >> check_asm.c
+	@echo "#undef CONFIG_SMP" >> check_asm.c
 	@echo "#include <linux/sched.h>" >> check_asm.c
 	@echo 'struct task_struct _task;' >> check_asm.c
 	@echo 'struct mm_struct _mm;' >> check_asm.c
@@ -69,11 +75,17 @@
 	./check_asm >> asm_offsets.h
 	@rm -f check_asm check_asm.c
 	@echo "" >> asm_offsets.h
-	@echo "#else /* __SMP__ */" >> asm_offsets.h
+	@echo "#else /* CONFIG_SMP */" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#include <linux/sched.h>" > tmp.c
+	@echo "#include <linux/config.h>" > tmp.c
+	@echo "#undef CONFIG_SMP" >> tmp.c
+	@echo "#define CONFIG_SMP 1" >> tmp.c
+	@echo "#include <linux/sched.h>" >> tmp.c
 	$(CC) -D__SMP__ -E tmp.c -o tmp.i
 	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
+	@echo "#include <linux/config.h>" >> check_asm.c
+	@echo "#undef CONFIG_SMP" >> check_asm.c
+	@echo "#define CONFIG_SMP 1" >> check_asm.c
 	@echo "#include <linux/sched.h>" >> check_asm.c
 	@echo 'struct task_struct _task;' >> check_asm.c
 	@echo 'struct mm_struct _mm;' >> check_asm.c
@@ -88,7 +100,7 @@
 	./check_asm >> asm_offsets.h
 	@rm -f check_asm check_asm.c
 	@echo "" >> asm_offsets.h
-	@echo "#endif /* __SMP__ */" >> asm_offsets.h
+	@echo "#endif /* CONFIG_SMP */" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
 	@echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h
 	@if test -r $(HPATH)/asm/asm_offsets.h; then \
diff -u --recursive --new-file v2.1.131/linux/arch/sparc/lib/Makefile linux/arch/sparc/lib/Makefile
--- v2.1.131/linux/arch/sparc/lib/Makefile	Thu Aug  6 14:06:30 1998
+++ linux/arch/sparc/lib/Makefile	Fri Dec 18 14:01:48 1998
@@ -7,7 +7,7 @@
 	strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \
 	copy_user.o locks.o atomic.o bitops.o debuglocks.o
 
-ifdef SMP
+ifdef CONFIG_SMP
 OBJS += irqlock.o
 endif
 
@@ -54,7 +54,7 @@
 bitops.o: bitops.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o bitops.o bitops.S
 
-ifdef SMP
+ifdef CONFIG_SMP
 irqlock.o: irqlock.S
 	$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c -o irqlock.o irqlock.S
 endif
diff -u --recursive --new-file v2.1.131/linux/arch/sparc/mm/Makefile linux/arch/sparc/mm/Makefile
--- v2.1.131/linux/arch/sparc/mm/Makefile	Mon Oct  5 13:13:37 1998
+++ linux/arch/sparc/mm/Makefile	Fri Dec 18 14:01:48 1998
@@ -14,7 +14,7 @@
 else
 O_OBJS	 += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o
 endif
-ifdef SMP
+ifdef CONFIG_SMP
 O_OBJS   += nosun4c.o
 else
 O_OBJS   += sun4c.o
diff -u --recursive --new-file v2.1.131/linux/arch/sparc64/Makefile linux/arch/sparc64/Makefile
--- v2.1.131/linux/arch/sparc64/Makefile	Sun Nov  8 14:02:46 1998
+++ linux/arch/sparc64/Makefile	Fri Dec 18 14:01:48 1998
@@ -51,7 +51,7 @@
 # Uncomment this to get spinlock/rwlock debugging on SMP.
 # DEBUG_SPINLOCK = 1
 
-ifdef SMP
+ifdef CONFIG_SMP
   ifdef DEBUG_SPINLOCK
     CFLAGS += -DSPIN_LOCK_DEBUG
     AFLAGS += -DSPIN_LOCK_DEBUG
diff -u --recursive --new-file v2.1.131/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.1.131/linux/arch/sparc64/config.in	Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/config.in	Fri Dec 18 14:01:48 1998
@@ -25,6 +25,7 @@
 define_bool CONFIG_VT_CONSOLE y
 
 bool 'Support for AP1000 multicomputer' CONFIG_AP1000
+bool 'Symmetric multi-processing support' CONFIG_SMP
 
 mainmenu_option next_comment
 comment 'Console drivers'
diff -u --recursive --new-file v2.1.131/linux/arch/sparc64/defconfig linux/arch/sparc64/defconfig
--- v2.1.131/linux/arch/sparc64/defconfig	Thu Nov 19 09:56:27 1998
+++ linux/arch/sparc64/defconfig	Fri Dec 18 14:01:48 1998
@@ -20,6 +20,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_AP1000 is not set
+# CONFIG_SMP is not set
 
 #
 # Console drivers
diff -u --recursive --new-file v2.1.131/linux/arch/sparc64/kernel/Makefile linux/arch/sparc64/kernel/Makefile
--- v2.1.131/linux/arch/sparc64/kernel/Makefile	Sun Nov  8 14:02:46 1998
+++ linux/arch/sparc64/kernel/Makefile	Fri Dec 18 14:01:48 1998
@@ -27,7 +27,7 @@
   O_OBJS += ebus.o
 endif
 
-ifdef SMP
+ifdef CONFIG_SMP
 O_OBJS += smp.o trampoline.o
 endif
 
@@ -63,11 +63,17 @@
 	@echo "#ifndef __ASM_OFFSETS_H__" >> asm_offsets.h
 	@echo "#define __ASM_OFFSETS_H__" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#ifndef __SMP__" >> asm_offsets.h
+	@echo "#include <linux/config.h>" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#include <linux/sched.h>" > tmp.c
+	@echo "#ifndef CONFIG_SMP" >> asm_offsets.h
+	@echo "" >> asm_offsets.h
+	@echo "#include <linux/config.h>" > tmp.c
+	@echo "#undef CONFIG_SMP" >> tmp.c
+	@echo "#include <linux/sched.h>" >> tmp.c
 	$(CC) -E tmp.c -o tmp.i
 	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
+	@echo "#include <linux/config.h>" >> check_asm.c
+	@echo "#undef CONFIG_SMP" >> check_asm.c
 	@echo "#include <linux/sched.h>" >> check_asm.c
 	@echo 'struct task_struct _task;' >> check_asm.c
 	@echo 'struct mm_struct _mm;' >> check_asm.c
@@ -87,13 +93,19 @@
 	./check_asm >> asm_offsets.h
 	@rm -f check_asm check_asm.c
 	@echo "" >> asm_offsets.h
-	@echo "#else /* __SMP__ */" >> asm_offsets.h
+	@echo "#else /* CONFIG_SMP */" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
 	@echo "#ifndef SPIN_LOCK_DEBUG" >>asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#include <linux/sched.h>" > tmp.c
+	@echo "#include <linux/config.h>" > tmp.c
+	@echo "#undef CONFIG_SMP" >> tmp.c
+	@echo "#define CONFIG_SMP 1" >> tmp.c
+	@echo "#include <linux/sched.h>" >> tmp.c
 	$(CC) -D__SMP__ -E tmp.c -o tmp.i
 	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
+	@echo "#include <linux/config.h>" >> check_asm.c
+	@echo "#undef CONFIG_SMP" >> check_asm.c
+	@echo "#define CONFIG_SMP 1" >> check_asm.c
 	@echo "#include <linux/sched.h>" >> check_asm.c
 	@echo 'struct task_struct _task;' >> check_asm.c
 	@echo 'struct mm_struct _mm;' >> check_asm.c
@@ -118,6 +130,9 @@
 	@echo "#include <linux/sched.h>" > tmp.c
 	$(CC) -D__SMP__ -DSPIN_LOCK_DEBUG -E tmp.c -o tmp.i
 	@echo "/* Automatically generated. Do not edit. */" > check_asm.c
+	@echo "#include <linux/config.h>" >> check_asm.c
+	@echo "#undef CONFIG_SMP" >> check_asm.c
+	@echo "#define CONFIG_SMP 1" >> check_asm.c
 	@echo "#include <linux/sched.h>" >> check_asm.c
 	@echo 'struct task_struct _task;' >> check_asm.c
 	@echo 'struct mm_struct _mm;' >> check_asm.c
@@ -138,7 +153,7 @@
 	@rm -f check_asm check_asm.c
 	@echo "#endif /* SPIN_LOCK_DEBUG */" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
-	@echo "#endif /* __SMP__ */" >> asm_offsets.h
+	@echo "#endif /* CONFIG_SMP */" >> asm_offsets.h
 	@echo "" >> asm_offsets.h
 	@echo "#endif /* __ASM_OFFSETS_H__ */" >> asm_offsets.h
 	@if test -r $(HPATH)/asm/asm_offsets.h; then \
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/block/ide-ics.c linux/drivers/acorn/block/ide-ics.c
--- v2.1.131/linux/drivers/acorn/block/ide-ics.c	Wed Sep  9 14:51:06 1998
+++ linux/drivers/acorn/block/ide-ics.c	Thu Dec 17 09:07:45 1998
@@ -27,6 +27,7 @@
 
 #define ICS_IDENT_OFFSET		0x8a0
 
+#define ICS_ARCIN_V5_INTRSTAT		0x000
 #define ICS_ARCIN_V5_INTROFFSET		0x001
 #define ICS_ARCIN_V5_IDEOFFSET		0xa00
 #define ICS_ARCIN_V5_IDEALTOFFSET	0xae0
@@ -34,9 +35,11 @@
 
 #define ICS_ARCIN_V6_IDEOFFSET_1	0x800
 #define ICS_ARCIN_V6_INTROFFSET_1	0x880
+#define ICS_ARCIN_V6_INTRSTAT_1		0x8a4
 #define ICS_ARCIN_V6_IDEALTOFFSET_1	0x8e0
 #define ICS_ARCIN_V6_IDEOFFSET_2	0xc00
 #define ICS_ARCIN_V6_INTROFFSET_2	0xc80
+#define ICS_ARCIN_V6_INTRSTAT_2		0xca4
 #define ICS_ARCIN_V6_IDEALTOFFSET_2	0xce0
 #define ICS_ARCIN_V6_IDESTEPPING	4
 
@@ -199,6 +202,8 @@
 
 	case ics_if_arcin_v5:
 		port = ecard_address (ec, ECARD_MEMC, 0);
+		ec->irqaddr = ioaddr(port + ICS_ARCIN_V5_INTRSTAT);
+		ec->irqmask = 1;
 		ec->irq_data = (void *)port;
 		ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5;
 
@@ -210,10 +215,13 @@
 							port + ICS_ARCIN_V5_IDEALTOFFSET,
 							ICS_ARCIN_V5_IDESTEPPING,
 							ec->irq);
+		result[index][1] = -1;
 		break;
 
 	case ics_if_arcin_v6:
 		port = ecard_address (ec, ECARD_IOC, ECARD_FAST);
+		ec->irqaddr = ioaddr(port + ICS_ARCIN_V6_INTRSTAT_1);
+		ec->irqmask = 1;
 		ec->irq_data = (void *)port;
 		ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6;
 
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/char/Config.in linux/drivers/acorn/char/Config.in
--- v2.1.131/linux/drivers/acorn/char/Config.in	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/char/Config.in	Thu Dec 17 09:07:45 1998
@@ -2,3 +2,14 @@
   tristate '   Atomwide serial port support' CONFIG_ATOMWIDE_SERIAL
   tristate '   Dual serial port support' CONFIG_DUALSP_SERIAL
 fi
+
+if [ "$CONFIG_MOUSE" = "y" ]; then
+  if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
+    if [ "$CONFIG_ARCH_RPC" != "y" ]; then
+      define_bool CONFIG_KBDMOUSE y
+    else
+      define_bool CONFIG_RPCMOUSE y
+    fi
+  fi
+fi
+
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile
--- v2.1.131/linux/drivers/acorn/char/Makefile	Fri May  8 23:14:46 1998
+++ linux/drivers/acorn/char/Makefile	Thu Dec 17 09:07:45 1998
@@ -13,6 +13,19 @@
 M_OBJS   :=
 L_OBJS   :=
 
+ifeq ($(MACHINE),rpc)
+  MOUSE_OBJS += mouse_rpc.o
+  L_OBJS += keyb_ps2.o
+endif
+
+ifeq ($(CONFIG_MOUSE),y)
+  LX_OBJS += $(MOUSE_OBJS)
+else
+  ifeq ($(CONFIG_MOUSE),m)
+    MX_OBJS += $(MOUSE_OBJS)
+  endif
+endif
+
 ifeq ($(CONFIG_ATOMWIDE_SERIAL),y)
   L_OBJS += serial-atomwide.o
 else
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c
--- v2.1.131/linux/drivers/acorn/char/keyb_ps2.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/keyb_ps2.c	Thu Dec 17 09:07:45 1998
@@ -0,0 +1,355 @@
+/*
+ * linux/arch/arm/drivers/block/keyb_ps2.c
+ *
+ * Keyboard driver for RPC ARM Linux.
+ *
+ * Note!!! This driver talks directly to the keyboard.
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/malloc.h>
+#include <linux/ptrace.h>
+#include <linux/signal.h>
+#include <linux/timer.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/kbd_ll.h>
+#include <linux/init.h>
+
+#include <asm/bitops.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+extern void kbd_reset_kdown(void);
+int kbd_read_mask;
+
+#define IRQ_KEYBOARDRX 15
+
+#define VERSION 100
+
+#define KBD_REPORT_ERR
+#define KBD_REPORT_UNKN
+
+#define KBD_ESCAPEE0	0xe0		/* in */
+#define KBD_ESCAPEE1	0xe1		/* in */
+
+#define ESCE0(x)	(0xe000|(x))
+#define ESCE1(x)	(0xe100|(x))
+
+#define KBD_BAT		0xaa		/* in */
+#define KBD_SETLEDS	0xed		/* out */
+#define KBD_ECHO	0xee		/* in/out */
+#define KBD_BREAK	0xf0		/* in */
+#define KBD_TYPRATEDLY	0xf3		/* out */
+#define KBD_SCANENABLE	0xf4		/* out */
+#define KBD_DEFDISABLE	0xf5		/* out */
+#define KBD_DEFAULT	0xf6		/* out */
+#define KBD_ACK		0xfa		/* in */
+#define KBD_DIAGFAIL	0xfd		/* in */
+#define KBD_RESEND	0xfe		/* in/out */
+#define KBD_RESET	0xff		/* out */
+
+#define CODE_BREAK	1
+#define CODE_ESCAPEE0	2
+#define CODE_ESCAPEE1	4
+#define CODE_ESCAPE12	8
+
+#define K_NONE		0x7f
+#define K_ESC		0x00
+#define K_F1		0x01
+#define K_F2		0x02
+#define K_F3		0x03
+#define K_F4		0x04
+#define K_F5		0x05
+#define K_F6		0x06
+#define K_F7		0x07
+#define K_F8		0x08
+#define K_F9		0x09
+#define K_F10		0x0a
+#define K_F11		0x0b
+#define K_F12		0x0c
+#define K_PRNT		0x0d
+#define K_SCRL		0x0e
+#define K_BRK		0x0f
+#define K_AGR		0x10
+#define K_1		0x11
+#define K_2		0x12
+#define K_3		0x13
+#define K_4		0x14
+#define K_5		0x15
+#define K_6		0x16
+#define K_7		0x17
+#define K_8		0x18
+#define K_9		0x19
+#define K_0		0x1a
+#define K_MINS		0x1b
+#define K_EQLS		0x1c
+#define K_BKSP		0x1e
+#define K_INS		0x1f
+#define K_HOME		0x20
+#define K_PGUP		0x21
+#define K_NUML		0x22
+#define KP_SLH		0x23
+#define KP_STR		0x24
+#define KP_MNS		0x3a
+#define K_TAB		0x26
+#define K_Q		0x27
+#define K_W		0x28
+#define K_E		0x29
+#define K_R		0x2a
+#define K_T		0x2b
+#define K_Y		0x2c
+#define K_U		0x2d
+#define K_I		0x2e
+#define K_O		0x2f
+#define K_P		0x30
+#define K_LSBK		0x31
+#define K_RSBK		0x32
+#define K_ENTR		0x47
+#define K_DEL		0x34
+#define K_END		0x35
+#define K_PGDN		0x36
+#define KP_7		0x37
+#define KP_8		0x38
+#define KP_9		0x39
+#define KP_PLS		0x4b
+#define K_CAPS		0x5d
+#define K_A		0x3c
+#define K_S		0x3d
+#define K_D		0x3e
+#define K_F		0x3f
+#define K_G		0x40
+#define K_H		0x41
+#define K_J		0x42
+#define K_K		0x43
+#define K_L		0x44
+#define K_SEMI		0x45
+#define K_SQOT		0x46
+#define K_HASH		0x1d
+#define KP_4		0x48
+#define KP_5		0x49
+#define KP_6		0x4a
+#define K_LSFT		0x4c
+#define K_BSLH		0x33
+#define K_Z		0x4e
+#define K_X		0x4f
+#define K_C		0x50
+#define K_V		0x51
+#define K_B		0x52
+#define K_N		0x53
+#define K_M		0x54
+#define K_COMA		0x55
+#define K_DOT		0x56
+#define K_FSLH		0x57
+#define K_RSFT		0x58
+#define K_UP		0x59
+#define KP_1		0x5a
+#define KP_2		0x5b
+#define KP_3		0x5c
+#define KP_ENT		0x67
+#define K_LCTL		0x3b
+#define K_LALT		0x5e
+#define K_SPCE		0x5f
+#define K_RALT		0x60
+#define K_RCTL		0x61
+#define K_LEFT		0x62
+#define K_DOWN		0x63
+#define K_RGHT		0x64
+#define KP_0		0x65
+#define KP_DOT		0x66
+
+static unsigned char keycode_translate[256] =
+{
+/* 00 */  K_NONE, K_F9  , K_NONE, K_F5  , K_F3  , K_F1  , K_F2  , K_F12 ,
+/* 08 */  K_NONE, K_F10 , K_F8  , K_F6  , K_F4  , K_TAB , K_AGR , K_NONE,
+/* 10 */  K_NONE, K_LALT, K_LSFT, K_NONE, K_LCTL, K_Q   , K_1   , K_NONE,
+/* 18 */  K_NONE, K_NONE, K_Z   , K_S   , K_A   , K_W   , K_2   , K_NONE,
+/* 20 */  K_NONE, K_C   , K_X   , K_D   , K_E   , K_4   , K_3   , K_NONE,
+/* 28 */  K_NONE, K_SPCE, K_V   , K_F   , K_T   , K_R   , K_5   , K_NONE,
+/* 30 */  K_NONE, K_N   , K_B   , K_H   , K_G   , K_Y   , K_6   , K_NONE,
+/* 38 */  K_NONE, K_NONE, K_M   , K_J   , K_U   , K_7   , K_8   , K_NONE,
+/* 40 */  K_NONE, K_COMA, K_K   , K_I   , K_O   , K_0   , K_9   , K_NONE,
+/* 48 */  K_NONE, K_DOT , K_FSLH, K_L   , K_SEMI, K_P   , K_MINS, K_NONE,
+/* 50 */  K_NONE, K_NONE, K_SQOT, K_NONE, K_LSBK, K_EQLS, K_NONE, K_NONE,
+/* 58 */  K_CAPS, K_RSFT, K_ENTR, K_RSBK, K_NONE, K_HASH, K_NONE, K_NONE,
+/* 60 */  K_NONE, K_BSLH, K_NONE, K_NONE, K_NONE, K_NONE, K_BKSP, K_NONE,
+/* 68 */  K_NONE, KP_1  , K_NONE, KP_4  , KP_7  , K_NONE, K_NONE, K_NONE,
+/* 70 */  KP_0  , KP_DOT, KP_2  , KP_5  , KP_6  , KP_8  , K_ESC , K_NUML,
+/* 78 */  K_F11 , KP_PLS, KP_3  , KP_MNS, KP_STR, KP_9  , K_SCRL, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_F7  , K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE,
+	  K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE, K_NONE
+};
+
+#ifdef CONFIG_MAGIC_SYSRQ
+unsigned char ps2kbd_sysrq_xlate[] = 
+{
+    27,    0,    0,    0,    0,    0,    0,    0,
+     0,    0,    0,    0,    0,    0,    0,    0,
+   '`',  '1',  '2',  '3',  '4',  '5',  '6',  '7',
+   '8',  '9',  '0',  '-',  '=',  '£',  127,    0,
+     0,    0,    0,  '/',  '*',  '#',    9,  'q',
+   'w',  'e',  'r',  't',  'y',  'u',  'i',  'o',
+   'p',  '[',  ']', '\\',  22,    23,   25,  '7',
+   '8',  '9',  '-',    0,  'a',  's',  'd',  'f',
+   'g',  'h',  'j',  'k',  'l',  ';', '\'',   13,
+   '4',  '5',  '6',  '+',    0,    0,  'z',  'x',
+   'c',  'v',  'b',  'n',  'm',  ',',  '.',  '/',
+     0,    0,  '1',  '2',  '3',    0,    0,  ' ',
+     0,    0,    0,    0,    0,  '0',  '.',   10,
+     0,    0,    0,    0,    0,    0,    0,    0,
+     0,    0,    0,    0,    0,    0,    0,    0,
+     0,    0,    0,    0,    0,    0,    0,    0,
+};
+#endif
+
+int ps2kbd_pretranslate(unsigned char scancode)
+{
+	return 1;
+}
+
+int ps2kbd_translate(unsigned char scancode, unsigned char *keycode_p, char *uf_p)
+{
+	*uf_p = scancode & 0200;
+	*keycode_p = scancode & 0x7f;
+	return 1;
+}
+
+static void ps2kbd_key(unsigned int keycode, unsigned int up_flag)
+{
+	handle_scancode(keycode + (up_flag ? 0x80 : 0));
+}
+
+static inline void ps2kbd_sendbyte(unsigned char val)
+{
+	while(!(inb(IOMD_KCTRL) & (1 << 7)));
+	outb(val, IOMD_KARTTX);
+}
+
+static unsigned char status;
+static unsigned char ncodes;
+static unsigned char bi;
+static unsigned char buffer[4];
+
+static inline void ps2kbd_reset(void)
+{
+	status = 0;
+	kbd_reset_kdown();
+}
+
+static void handle_rawcode(int keyval)
+{
+	int keysym;
+
+	if (keyval > 0x83) {
+		switch (keyval) {
+			case KBD_ESCAPEE0:
+				ncodes = 2;
+				bi = 0;
+				break;
+			case KBD_ESCAPEE1:
+				ncodes = 3;
+				bi = 0;
+				break;
+			case KBD_BREAK:
+				status |= CODE_BREAK;
+			default:
+				return;
+		}
+	}
+
+	if (ncodes) {
+		buffer[bi++] = keyval;
+		ncodes -= 1;
+		if (ncodes)
+			return;
+		keysym = K_NONE;
+		switch (buffer[0] << 8 | buffer[1]) {
+		case ESCE0(0x11): keysym = K_RALT; break;
+		case ESCE0(0x14): keysym = K_RCTL; break;
+		case ESCE0(0x4a): keysym = KP_SLH; break;
+		case ESCE0(0x5a): keysym = KP_ENT; break;
+		case ESCE0(0x69): keysym = K_END;  break;
+		case ESCE0(0x6b): keysym = K_LEFT; break;
+		case ESCE0(0x6c): keysym = K_HOME; break;
+		case ESCE0(0x70): keysym = K_INS;  break;
+		case ESCE0(0x71): keysym = K_DEL;  break;
+		case ESCE0(0x72): keysym = K_DOWN; break;
+		case ESCE0(0x74): keysym = K_RGHT; break;
+		case ESCE0(0x75): keysym = K_UP;   break;
+		case ESCE0(0x7a): keysym = K_PGDN; break;
+		case ESCE0(0x7c): keysym = K_PRNT; break;
+		case ESCE0(0x7d): keysym = K_PGUP; break;
+		case ESCE1(0x14):
+			if (buffer[2] == 0x77)
+				keysym = K_BRK;
+			break;
+		case ESCE0(0x12):		/* ignore escaped shift key */
+			status = 0;
+			return;
+		}
+	} else {
+		bi = 0;
+		keysym = keycode_translate[keyval];
+	}
+
+	if (keysym != K_NONE)
+		ps2kbd_key(keysym, status & CODE_BREAK);
+	status = 0;
+}
+
+void ps2kbd_leds(unsigned int leds)
+{
+	ps2kbd_sendbyte(KBD_SETLEDS);
+	ps2kbd_sendbyte(leds);
+	ps2kbd_sendbyte(KBD_SCANENABLE);
+}
+
+static void ps2kbd_rx(int irq, void *dev_id, struct pt_regs *regs)
+{
+	kbd_pt_regs = regs;
+
+	while (inb(IOMD_KCTRL) & (1 << 5))
+		handle_rawcode(inb(IOMD_KARTRX));
+	mark_bh(KEYBOARD_BH);
+}
+
+static void ps2kbd_tx(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+__initfunc(int ps2kbd_init_hw(void))
+{
+	unsigned long flags;
+
+	save_flags_cli (flags);
+	if (request_irq (IRQ_KEYBOARDRX, ps2kbd_rx, 0, "keyboard", NULL) != 0)
+		panic("Could not allocate keyboard receive IRQ!");
+	if (request_irq (IRQ_KEYBOARDTX, ps2kbd_tx, 0, "keyboard", NULL) != 0)
+		panic("Could not allocate keyboard transmit IRQ!");
+	disable_irq (IRQ_KEYBOARDTX);
+	(void)IOMD_KARTRX;
+	restore_flags (flags);
+
+	printk (KERN_INFO "PS/2 keyboard driver v%d.%02d\n", VERSION/100, VERSION%100);
+	return 0;
+}
+
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/char/mouse_rpc.c linux/drivers/acorn/char/mouse_rpc.c
--- v2.1.131/linux/drivers/acorn/char/mouse_rpc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/acorn/char/mouse_rpc.c	Thu Dec 17 09:07:45 1998
@@ -0,0 +1,86 @@
+/*
+ * linux/drivers/char/rpcmouse.c
+ *
+ * Copyright (C) 1996-1998 Russell King
+ *
+ * This handles the Acorn RiscPCs mouse.  We basically have a couple
+ * of hardware registers that track the sensor count for the X-Y movement
+ * and another register holding the button state.  On every VSYNC interrupt
+ * we read the complete state and then work out if something has changed.
+ */
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/ptrace.h>
+#include <linux/interrupt.h>
+
+#include <asm/hardware.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+#include "../../char/mouse.h"
+
+static short old_x, old_y, old_b;
+static int mousedev;
+
+void
+mouse_rpc_irq(int irq, void *dev_id, struct pt_regs *regs)
+{
+	short x, y, dx, dy;
+	int buttons;
+
+	x = (short)inl(IOMD_MOUSEX);
+	y = (short)inl(IOMD_MOUSEY);
+	buttons = (inl (0x800C4000) >> 4) & 7;
+
+	dx = x - old_x;
+	old_x = x;
+	dy = y - old_y;
+	old_y = y;
+
+	if (dx || dy || buttons != old_b) {
+		busmouse_add_movementbuttons(mousedev, dx, dy, buttons);
+		old_b = buttons;
+	}
+}
+
+static struct busmouse rpcmouse = {
+	6, "arcmouse", NULL, NULL, 7
+};
+
+int
+mouse_rpc_init(void)
+{
+	mousedev = register_busmouse(&rpcmouse);
+
+	if (mousedev < 0)
+		printk("rpcmouse: could not register mouse driver\n");
+	else {
+		old_x = (short)inl(IOMD_MOUSEX);
+		old_y = (short)inl(IOMD_MOUSEY);
+		old_b = (inl (0x800C4000) >> 4) & 7;
+		if (request_irq(IRQ_VSYNCPULSE, mouse_rpc_irq, SA_SHIRQ, "mouse", &mousedev)) {
+			printk("rpcmouse: unable to allocate VSYNC interrupt\n");
+			unregister_busmouse(mousedev);
+			mousedev = -1;
+		}
+	}
+
+	return mousedev >= 0 ? 0 : -ENODEV;
+}
+
+#ifdef MODULE
+int
+init_module(void)
+{
+	return mouse_rpc_init();
+}
+
+int
+cleanup_module(void)
+{
+	if (mousedev >= 0) {
+		unregister_busmouse(mousedev);
+		free_irq(IRQ_VSYNCPULSE, &mousedev);
+	}
+}
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.1.131/linux/drivers/acorn/net/etherh.c	Tue Jul 21 00:15:30 1998
+++ linux/drivers/acorn/net/etherh.c	Thu Dec 17 09:07:45 1998
@@ -186,7 +186,7 @@
 	
 	if (ei_status.dmaing) {
 		printk ("%s: DMAing conflict in etherh_block_input: "
-			" DMAstat %d irqlock %d intr %d\n", dev->name,
+			" DMAstat %d irqlock %d intr %ld\n", dev->name,
 			ei_status.dmaing, ei_status.irqlock, dev->interrupt);
 		return;
 	}
@@ -246,7 +246,7 @@
 
 	if (ei_status.dmaing) {
 		printk ("%s: DMAing conflict in etherh_block_input: "
-			" DMAstat %d irqlock %d intr %d\n", dev->name,
+			" DMAstat %d irqlock %d intr %ld\n", dev->name,
 			ei_status.dmaing, ei_status.irqlock, dev->interrupt);
 		return;
 	}
@@ -288,7 +288,7 @@
 
 	if (ei_status.dmaing) {
 		printk ("%s: DMAing conflict in etherh_get_header: "
-			" DMAstat %d irqlock %d intr %d\n", dev->name,
+			" DMAstat %d irqlock %d intr %ld\n", dev->name,
 			ei_status.dmaing, ei_status.irqlock, dev->interrupt);
 		return;
 	}
@@ -469,9 +469,9 @@
 	ecard_claim (ec);
 	
 	dev->irq = ec->irq;
-	dev->mem_end = ec->cld.product;
+	dev->mem_end = ec->cid.product;
 
-	switch (ec->cld.product) {
+	switch (ec->cid.product) {
 	case PROD_I3_ETHERLAN500:
 		dev->base_addr = ecard_address (ec, ECARD_MEMC, 0) + ETHERH500_NS8390;
 		dev->mem_start = dev->base_addr + ETHERH500_DATAPORT;
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/scsi/acornscsi.c linux/drivers/acorn/scsi/acornscsi.c
--- v2.1.131/linux/drivers/acorn/scsi/acornscsi.c	Tue Jul 21 00:15:30 1998
+++ linux/drivers/acorn/scsi/acornscsi.c	Thu Dec 17 09:07:45 1998
@@ -148,10 +148,11 @@
 #include "../../scsi/hosts.h"
 #include "../../scsi/constants.h"
 #include "acornscsi.h"
+#include "msgqueue.h"
 
 #define VER_MAJOR 2
 #define VER_MINOR 0
-#define VER_PATCH 5
+#define VER_PATCH 6
 
 #ifndef ABORT_TAG
 #define ABORT_TAG 0xd
@@ -177,6 +178,8 @@
 #define DMAC_WRITE	(MODECON_WRITE)
 #define INIT_SBICDMA	(CTRL_DMABURST)
 
+#define scsi_xferred	have_data_in
+
 /*
  * Size of on-board DMA buffer
  */
@@ -259,6 +262,29 @@
 	   dmac_read (io_port, TXADRMD) << 8 |
 	   dmac_read (io_port, TXADRLO);
 }
+
+static
+void acornscsi_dumpdma (AS_Host *host, char *where)
+{
+	unsigned int mode, addr, len;
+
+	mode = dmac_read (host->dma.io_port, MODECON);
+	addr = dmac_address (host->dma.io_port);
+	len  = dmac_read (host->dma.io_port, TXCNTHI) << 8 |
+	       dmac_read (host->dma.io_port, TXCNTLO);
+
+	printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
+		host->host->host_no, where,
+		mode, addr, (len + 1) & 0xffff,
+		dmac_read (host->dma.io_port, MASKREG));
+
+	printk ("DMA @%06x, ", host->dma.start_addr);
+	printk ("BH @%p +%04x, ", host->scsi.SCp.ptr,
+		host->scsi.SCp.this_residual);
+	printk ("DT @+%04x ST @+%04x", host->dma.transferred,
+		host->scsi.SCp.scsi_xferred);
+	printk ("\n");
+}
 #endif
 
 static
@@ -345,15 +371,13 @@
     host->card.page_reg = 0x40;
     outb (host->card.page_reg, host->card.io_page);
 
-#ifdef USE_DMAC
     /* setup dmac - uPC71071 */
-    dmac_write (host->dma.io_port, INIT, 0);
-    dmac_write (host->dma.io_port, INIT, INIT_8BIT);
-    dmac_write (host->dma.io_port, CHANNEL, CHANNEL_0);
-    dmac_write (host->dma.io_port, DEVCON0, INIT_DEVCON0);
-    dmac_write (host->dma.io_port, DEVCON1, INIT_DEVCON1);
-#else
-    dmac_write (host->dma.io_port, INIT, 0);
+    dmac_write(host->dma.io_port, INIT, 0);
+#ifdef USE_DMAC
+    dmac_write(host->dma.io_port, INIT, INIT_8BIT);
+    dmac_write(host->dma.io_port, CHANNEL, CHANNEL_0);
+    dmac_write(host->dma.io_port, DEVCON0, INIT_DEVCON0);
+    dmac_write(host->dma.io_port, DEVCON1, INIT_DEVCON1);
 #endif
 
     host->SCpnt = NULL;
@@ -517,31 +541,6 @@
 	return 'H';
 }
 
-#ifdef USE_DMAC
-static
-void acornscsi_dumpdma (AS_Host *host, char *where)
-{
-	unsigned int mode, addr, len;
-
-	mode = dmac_read (host->dma.io_port, MODECON);
-	addr = dmac_address (host->dma.io_port);
-	len  = dmac_read (host->dma.io_port, TXCNTHI) << 8 |
-	       dmac_read (host->dma.io_port, TXCNTLO);
-
-	printk ("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",
-		host->host->host_no, where,
-		mode, addr, (len + 1) & 0xffff,
-		dmac_read (host->dma.io_port, MASKREG));
-
-	printk ("DMA @%06x, ", host->dma.start_addr);
-	printk ("BH @%p +%04x, ", host->scsi.SCp.ptr,
-		host->scsi.SCp.this_residual);
-	printk ("DT @+%04x ST @+%04x", host->dma.transferred,
-		host->scsi.SCp.have_data_in);
-	printk ("\n");
-}
-#endif
-
 /*
  * Prototype: cmdtype_t acornscsi_cmdtype (int command)
  * Purpose  : differentiate READ from WRITE from other commands
@@ -1051,7 +1050,7 @@
 	host->dma.xfer_setup = 0;
 
 #if (DEBUG & DEBUG_DMA)
-	DBG(host->SCpnt, acornscsi_dumpdma (host, "clup"));
+	DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi"));
 #endif
 
 	/*
@@ -1068,6 +1067,9 @@
 	 * Update SCSI pointers
 	 */
 	acornscsi_data_updateptr (host, &host->scsi.SCp, transferred);
+#if (DEBUG & DEBUG_DMA)
+	DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo"));
+#endif
     }
 }
 
@@ -1193,15 +1195,15 @@
 	/*
 	 * Calculate correct DMA address - DMA is ahead of SCSI bus while
 	 * writing.
-	 *  host->scsi.SCp.have_data_in is the number of bytes
+	 *  host->scsi.SCp.scsi_xferred is the number of bytes
 	 *  actually transferred to/from the SCSI bus.
 	 *  host->dma.transferred is the number of bytes transferred
 	 *  over DMA since host->dma.start_addr was last set.
 	 *
-	 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.have_data_in
+	 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred
 	 *		   - host->dma.transferred
 	 */
-	transferred = host->scsi.SCp.have_data_in - host->dma.transferred;
+	transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred;
 	if (transferred < 0)
 	    printk ("scsi%d.%c: Ack! DMA write correction %ld < 0!\n",
 		    host->host->host_no, acornscsi_target (host), transferred);
@@ -1259,8 +1261,8 @@
 void acornscsi_sendmessage (AS_Host *host)
 {
     unsigned int message_length = msgqueue_msglength (&host->scsi.msgs);
-    int msglen;
-    char *msg;
+    int msgnr;
+    struct message *msg;
 
 #if (DEBUG & DEBUG_MESSAGES)
     printk ("scsi%d.%c: sending message ",
@@ -1280,12 +1282,12 @@
 
     case 1:
 	acornscsi_sbic_issuecmd (host, CMND_XFERINFO | CMND_SBT);
-	msg = msgqueue_getnextmsg (&host->scsi.msgs, &msglen);
+	msg = msgqueue_getmsg(&host->scsi.msgs, 0);
 	while ((sbic_arm_read (host->scsi.io_port, ASR) & ASR_DBR) == 0);
-	sbic_arm_write (host->scsi.io_port, DATA, msg[0]);
-	host->scsi.last_message = msg[0];
+	sbic_arm_write (host->scsi.io_port, DATA, msg->msg[0]);
+	host->scsi.last_message = msg->msg[0];
 #if (DEBUG & DEBUG_MESSAGES)
-	print_msg (msg);
+	print_msg(msg->msg);
 #endif
 	break;
 
@@ -1303,21 +1305,22 @@
 	sbic_arm_writenext (host->scsi.io_port, message_length);
 	acornscsi_sbic_issuecmd (host, CMND_XFERINFO);
 
-	while ((msg = msgqueue_getnextmsg (&host->scsi.msgs, &msglen)) != NULL) {
+	msgnr = 0;
+	while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) {
 	    unsigned int asr, i;
 #if (DEBUG & DEBUG_MESSAGES)
 	    print_msg (msg);
 #endif
-	    for (i = 0; i < msglen;) {
+	    for (i = 0; i < msg->length;) {
 		asr = sbic_arm_read (host->scsi.io_port, ASR);
 		if (asr & ASR_DBR)
-		    sbic_arm_write (host->scsi.io_port, DATA, msg[i++]);
+		    sbic_arm_write (host->scsi.io_port, DATA, msg->msg[i++]);
 		if (asr & ASR_INT)
 		    break;
 	    }
-	    host->scsi.last_message = msg[0];
-	    if (msg[0] == EXTENDED_MESSAGE)
-		host->scsi.last_message |= msg[2] << 8;
+	    host->scsi.last_message = msg->msg[0];
+	    if (msg->msg[0] == EXTENDED_MESSAGE)
+		host->scsi.last_message |= msg->msg[2] << 8;
 	    if (asr & ASR_INT)
 		break;
 	}
@@ -1401,10 +1404,10 @@
     } while (msgidx < msglen);
 
 #if (DEBUG & DEBUG_MESSAGES)
-    printk (KERN_DEBUG "scsi%d.%c: message in: ",
+    printk("scsi%d.%c: message in: ",
 	    host->host->host_no, acornscsi_target (host));
-    print_msg (message);
-    printk ("\n");
+    print_msg(message);
+    printk("\n");
 #endif
 
     if (host->scsi.phase == PHASE_RECONNECTED) {
@@ -1424,9 +1427,11 @@
     case ABORT:
     case ABORT_TAG:
     case COMMAND_COMPLETE:
-	if (host->scsi.phase != PHASE_STATUSIN)
-	    printk (KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
+	if (host->scsi.phase != PHASE_STATUSIN) {
+	    printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n",
 		    host->host->host_no, acornscsi_target (host));
+	    acornscsi_dumplog(host, host->SCpnt->target);
+	}
 	host->scsi.phase = PHASE_DONE;
 	host->scsi.SCp.Message = message[0];
 	break;
@@ -1594,7 +1599,7 @@
 	 */
 	if (0) {
 #if (DEBUG & DEBUG_LINK)
-	    printk (KERN_DEBUG "scsi%d.%c: lun %d tag %d linked command complete\n",
+	    printk("scsi%d.%c: lun %d tag %d linked command complete\n",
 		    host->host->host_no, acornscsi_target(host), host->SCpnt->tag);
 #endif
 	    /*
@@ -1704,7 +1709,7 @@
 	return 0;
     }
 
-    residual = host->SCpnt->request_bufflen - host->scsi.SCp.have_data_in;
+    residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred;
 
     sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer);
     sbic_arm_writenext (host->scsi.io_port, residual >> 16);
@@ -1833,7 +1838,7 @@
     printk ("\n");
 #endif
 
-    host->dma.transferred = host->scsi.SCp.have_data_in;
+    host->dma.transferred = host->scsi.SCp.scsi_xferred;
 
     return host->SCpnt != NULL;
 }
@@ -1935,7 +1940,7 @@
 	    /* BUS FREE -> SELECTION */
 	    host->scsi.phase = PHASE_CONNECTED;
 	    msgqueue_flush (&host->scsi.msgs);
-	    host->dma.transferred = host->scsi.SCp.have_data_in;
+	    host->dma.transferred = host->scsi.SCp.scsi_xferred;
 	    /* 33C93 gives next interrupt indicating bus phase */
 	    asr = sbic_arm_read (host->scsi.io_port, ASR);
 	    if (!(asr & ASR_INT))
@@ -2178,7 +2183,7 @@
 	case 0x4b:			/* -> PHASE_STATUSIN				*/
 	case 0x1b:			/* -> PHASE_STATUSIN				*/
 	    /* DATA IN -> STATUS */
-	    host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
 					  acornscsi_sbic_xfcount (host);
 	    acornscsi_dma_stop (host);
 	    acornscsi_readstatusbyte (host);
@@ -2188,7 +2193,7 @@
 	case 0x1e:			/* -> PHASE_MSGOUT				*/
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
 	    /* DATA IN -> MESSAGE OUT */
-	    host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
 					  acornscsi_sbic_xfcount (host);
 	    acornscsi_dma_stop (host);
 	    acornscsi_sendmessage (host);
@@ -2197,7 +2202,7 @@
 	case 0x1f:			/* message in					*/
 	case 0x4f:			/* message in					*/
 	    /* DATA IN -> MESSAGE IN */
-	    host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
 					  acornscsi_sbic_xfcount (host);
 	    acornscsi_dma_stop (host);
 	    acornscsi_message (host);	/* -> PHASE_MSGIN, PHASE_DISCONNECT		*/
@@ -2223,7 +2228,7 @@
 	case 0x4b:			/* -> PHASE_STATUSIN				*/
 	case 0x1b:			/* -> PHASE_STATUSIN				*/
 	    /* DATA OUT -> STATUS */
-	    host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
 					  acornscsi_sbic_xfcount (host);
 	    acornscsi_dma_stop (host);
 	    acornscsi_dma_adjust (host);
@@ -2234,7 +2239,7 @@
 	case 0x1e:			/* -> PHASE_MSGOUT				*/
 	case 0x4e:			/* -> PHASE_MSGOUT				*/
 	    /* DATA OUT -> MESSAGE OUT */
-	    host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
 					  acornscsi_sbic_xfcount (host);
 	    acornscsi_dma_stop (host);
 	    acornscsi_dma_adjust (host);
@@ -2244,7 +2249,7 @@
 	case 0x1f:			/* message in					*/
 	case 0x4f:			/* message in					*/
 	    /* DATA OUT -> MESSAGE IN */
-	    host->scsi.SCp.have_data_in = host->SCpnt->request_bufflen -
+	    host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen -
 					  acornscsi_sbic_xfcount (host);
 	    acornscsi_dma_stop (host);
 	    acornscsi_dma_adjust (host);
@@ -2426,7 +2431,7 @@
     SCpnt->tag = 0;
     SCpnt->SCp.phase = (int)acornscsi_datadirection (SCpnt->cmnd[0]);
     SCpnt->SCp.sent_command = 0;
-    SCpnt->SCp.have_data_in = 0;
+    SCpnt->SCp.scsi_xferred = 0;
     SCpnt->SCp.Status = 0;
     SCpnt->SCp.Message = 0;
 
@@ -2592,7 +2597,7 @@
 	SCpnt->result = DID_RESET << 16;
 	SCpnt->scsi_done (SCpnt);
     }
-while (1);
+
     return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS;
 }
 
@@ -2657,6 +2662,9 @@
 	host->card.io_ram	= ioaddr (instance->io_port);
 	host->dma.io_port	= instance->io_port + 0xc00;
 	host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800;
+
+	ecs[count]->irqaddr	= (char *)ioaddr(host->card.io_intr);
+	ecs[count]->irqmask	= 0x0a;
 
 	request_region (instance->io_port + 0x800,  2, "acornscsi(sbic)");
 	request_region (host->card.io_intr,  1, "acornscsi(intr)");
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c
--- v2.1.131/linux/drivers/acorn/scsi/cumana_2.c	Wed Sep  9 14:51:07 1998
+++ linux/drivers/acorn/scsi/cumana_2.c	Thu Dec 17 09:07:45 1998
@@ -156,8 +156,6 @@
 static void
 cumanascsi_2_invalidate(char *addr, long len, fasdmadir_t direction)
 {
-	unsigned int page;
-
 	if (direction == DMA_OUT)
 		dma_cache_wback((unsigned long)addr, (unsigned long)len);
 	else
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c
--- v2.1.131/linux/drivers/acorn/scsi/eesox.c	Wed Sep  9 14:51:07 1998
+++ linux/drivers/acorn/scsi/eesox.c	Thu Dec 17 09:07:45 1998
@@ -164,8 +164,6 @@
 static void
 eesoxscsi_invalidate(char *addr, long len, fasdmadir_t direction)
 {
-	unsigned int page;
-
 	if (direction == DMA_OUT)
 		dma_cache_wback((unsigned long)addr, (unsigned long)len);
 	else
diff -u --recursive --new-file v2.1.131/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c
--- v2.1.131/linux/drivers/acorn/scsi/powertec.c	Wed Sep  9 14:51:07 1998
+++ linux/drivers/acorn/scsi/powertec.c	Thu Dec 17 09:07:45 1998
@@ -152,8 +152,6 @@
 static void
 powertecscsi_invalidate(char *addr, long len, fasdmadir_t direction)
 {
-	unsigned int page;
-
 	if (direction == DMA_OUT)
 		dma_cache_wback((unsigned long)addr, (unsigned long)len);
 	else
diff -u --recursive --new-file v2.1.131/linux/drivers/block/nbd.c linux/drivers/block/nbd.c
--- v2.1.131/linux/drivers/block/nbd.c	Sat Sep  5 16:46:40 1998
+++ linux/drivers/block/nbd.c	Wed Dec 16 13:38:18 1998
@@ -44,8 +44,9 @@
 
 #define LO_MAGIC 0x68797548
 
-static int nbd_blksizes[MAX_NBD] = {1024, 1024,};
-static int nbd_sizes[MAX_NBD] = {0x7fffffff, 0x7fffffff,};
+static int nbd_blksizes[MAX_NBD];
+static int nbd_sizes[MAX_NBD];
+static int nbd_bytesizes[MAX_NBD];
 
 static struct nbd_device nbd_dev[MAX_NBD];
 
@@ -382,9 +383,11 @@
 		if ((arg & 511) || (arg > PAGE_SIZE))
 			return -EINVAL;
 		nbd_blksizes[dev] = arg;
+		nbd_sizes[dev] = arg/nbd_blksizes[dev];
 		return 0;
 	case NBD_SET_SIZE:
-		nbd_sizes[dev] = arg;
+		nbd_bytesizes[dev] = arg;
+		nbd_sizes[dev] = arg/nbd_blksizes[dev];
 		return 0;
 	case NBD_DO_IT:
 		if (!lo->file)
@@ -400,6 +403,8 @@
 		       dev, (long) lo->head, (long) lo->tail, requests_in, requests_out);
 		return 0;
 #endif
+	case BLKGETSIZE:
+		return put_user(nbd_bytesizes[dev]/512, (long *) arg);
 	}
 	return -EINVAL;
 }
@@ -472,6 +477,9 @@
 		nbd_dev[i].file = NULL;
 		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];
 	}
 	return 0;
 }
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/Config.in linux/drivers/block/paride/Config.in
--- v2.1.131/linux/drivers/block/paride/Config.in	Tue Jun 23 10:01:22 1998
+++ linux/drivers/block/paride/Config.in	Tue Dec 22 08:29:00 1998
@@ -16,6 +16,7 @@
 dep_tristate '    FIT TD-3000 protocol' CONFIG_PARIDE_FIT3 $CONFIG_PARIDE
 dep_tristate '    Shuttle EPAT/EPEZ protocol' CONFIG_PARIDE_EPAT $CONFIG_PARIDE
 dep_tristate '    Shuttle EPIA protocol' CONFIG_PARIDE_EPIA $CONFIG_PARIDE
+dep_tristate '    Freecom IQ ASIC-2 protocol' CONFIG_PARIDE_FRIQ $CONFIG_PARIDE
 dep_tristate '    FreeCom power protocol' CONFIG_PARIDE_FRPW $CONFIG_PARIDE
 dep_tristate '    KingByte KBIC-951A/971A protocols' CONFIG_PARIDE_KBIC $CONFIG_PARIDE
 dep_tristate '    KT PHd protocol' CONFIG_PARIDE_KTTI $CONFIG_PARIDE
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/Makefile linux/drivers/block/paride/Makefile
--- v2.1.131/linux/drivers/block/paride/Makefile	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/Makefile	Tue Dec 22 08:29:00 1998
@@ -147,6 +147,15 @@
   endif
 endif
 
+
+ifeq ($(CONFIG_PARIDE_FRIQ),y)
+  LX_OBJS += friq.o
+else
+  ifeq ($(CONFIG_PARIDE_FRIQ),m)
+    M_OBJS += friq.o
+  endif
+endif
+
 ifeq ($(CONFIG_PARIDE_ON20),y)
   LX_OBJS += on20.o
 else
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/friq.c linux/drivers/block/paride/friq.c
--- v2.1.131/linux/drivers/block/paride/friq.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/block/paride/friq.c	Tue Dec 22 08:29:00 1998
@@ -0,0 +1,282 @@
+/* 
+	friq.c	(c) 1998    Grant R. Guenther <grant@torque.net>
+		            Under the terms of the GNU public license
+
+	friq.c is a low-level protocol driver for the Freecom "IQ"
+	parallel port IDE adapter.   Early versions of this adapter
+	use the 'frpw' protocol.
+	
+	Freecom uses this adapter in a battery powered external 
+	CD-ROM drive.  It is also used in LS-120 drives by
+	Maxell and Panasonic, and other devices.
+
+	The battery powered drive requires software support to
+	control the power to the drive.  This module enables the
+	drive power when the high level driver (pcd) is loaded
+	and disables it when the module is unloaded.  Note, if
+	the friq module is built in to the kernel, the power
+	will never be switched off, so other means should be
+	used to conserve battery power.
+
+*/
+
+/* Changes:
+
+	1.01	GRG 1998.12.20	 Added support for soft power switch
+*/
+
+#define	FRIQ_VERSION	"1.01" 
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <asm/io.h>
+
+#include "paride.h"
+
+#define CMD(x)		w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\
+			w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x);
+
+#define j44(l,h)	(((l>>4)&0x0f)|(h&0xf0))
+
+/* cont = 0 - access the IDE register file 
+   cont = 1 - access the IDE command set 
+*/
+
+static int  cont_map[2] = { 0x08, 0x10 };
+
+static int friq_read_regr( PIA *pi, int cont, int regr )
+
+{	int	h,l,r;
+
+	r = regr + cont_map[cont];
+
+	CMD(r);
+	w2(6); l = r1();
+	w2(4); h = r1();
+	w2(4); 
+
+	return j44(l,h);
+
+}
+
+static void friq_write_regr( PIA *pi, int cont, int regr, int val)
+
+{	int r;
+
+        r = regr + cont_map[cont];
+
+	CMD(r);
+	w0(val);
+	w2(5);w2(7);w2(5);w2(4);
+}
+
+static void friq_read_block_int( PIA *pi, char * buf, int count, int regr )
+
+{       int     h, l, k, ph;
+
+        switch(pi->mode) {
+
+        case 0: CMD(regr); 
+                for (k=0;k<count;k++) {
+                        w2(6); l = r1();
+                        w2(4); h = r1();
+                        buf[k] = j44(l,h);
+                }
+                w2(4);
+                break;
+
+        case 1: ph = 2;
+                CMD(regr+0xc0); 
+                w0(0xff);
+                for (k=0;k<count;k++) {
+                        w2(0xa4 + ph); 
+                        buf[k] = r0();
+                        ph = 2 - ph;
+                } 
+                w2(0xac); w2(0xa4); w2(4);
+                break;
+
+	case 2: CMD(regr+0x80);
+		for (k=0;k<count-2;k++) buf[k] = r4();
+		w2(0xac); w2(0xa4);
+		buf[count-2] = r4();
+		buf[count-1] = r4();
+		w2(4);
+		break;
+
+	case 3: CMD(regr+0x80);
+                for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
+                w2(0xac); w2(0xa4);
+                buf[count-2] = r4();
+                buf[count-1] = r4();
+                w2(4);
+                break;
+
+	case 4: CMD(regr+0x80);
+                for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
+                buf[count-4] = r4();
+                buf[count-3] = r4();
+                w2(0xac); w2(0xa4);
+                buf[count-2] = r4();
+                buf[count-1] = r4();
+                w2(4);
+                break;
+
+        }
+}
+
+static void friq_read_block( PIA *pi, char * buf, int count)
+
+{	friq_read_block_int(pi,buf,count,0x08);
+}
+
+static void friq_write_block( PIA *pi, char * buf, int count )
+ 
+{	int	k;
+
+	switch(pi->mode) {
+
+	case 0:
+	case 1: CMD(8); w2(5);
+        	for (k=0;k<count;k++) {
+			w0(buf[k]);
+			w2(7);w2(5);
+		}
+		w2(4);
+		break;
+
+	case 2: CMD(0xc8); w2(5);
+		for (k=0;k<count;k++) w4(buf[k]);
+		w2(4);
+		break;
+
+        case 3: CMD(0xc8); w2(5);
+                for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
+                w2(4);
+                break;
+
+        case 4: CMD(0xc8); w2(5);
+                for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
+                w2(4);
+                break;
+	}
+}
+
+static void friq_connect ( PIA *pi  )
+
+{       pi->saved_r0 = r0();
+        pi->saved_r2 = r2();
+	w2(4);
+}
+
+static void friq_disconnect ( PIA *pi )
+
+{       CMD(0x20);
+	w0(pi->saved_r0);
+        w2(pi->saved_r2);
+} 
+
+static int friq_test_proto( PIA *pi, char * scratch, int verbose )
+
+{       int     j, k, r;
+	int	e[2] = {0,0};
+
+	pi->saved_r0 = r0();	
+	w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
+	udelay(500);
+	w0(pi->saved_r0);
+
+	friq_connect(pi);
+	for (j=0;j<2;j++) {
+                friq_write_regr(pi,0,6,0xa0+j*0x10);
+                for (k=0;k<256;k++) {
+                        friq_write_regr(pi,0,2,k^0xaa);
+                        friq_write_regr(pi,0,3,k^0x55);
+                        if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
+                        }
+                }
+	friq_disconnect(pi);
+
+	friq_connect(pi);
+        friq_read_block_int(pi,scratch,512,0x10);
+        r = 0;
+        for (k=0;k<128;k++) if (scratch[k] != k) r++;
+	friq_disconnect(pi);
+
+        if (verbose)  {
+            printk("%s: friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
+                   pi->device,pi->port,pi->mode,e[0],e[1],r);
+        }
+
+        return (r || (e[0] && e[1]));
+}
+
+
+static void friq_log_adapter( PIA *pi, char * scratch, int verbose )
+
+{       char    *mode_string[6] = {"4-bit","8-bit",
+				   "EPP-8","EPP-16","EPP-32"};
+
+        printk("%s: friq %s, Freecom IQ ASIC-2 adapter at 0x%x, ", pi->device,
+		FRIQ_VERSION,pi->port);
+        printk("mode %d (%s), delay %d\n",pi->mode,
+		mode_string[pi->mode],pi->delay);
+
+	pi->private = 1;
+	friq_connect(pi);
+	CMD(0x9e);  		/* disable sleep timer */
+	friq_disconnect(pi);
+
+}
+
+static void friq_init_proto( PIA *pi)
+
+{       MOD_INC_USE_COUNT;
+	pi->private = 0;
+}
+
+static void friq_release_proto( PIA *pi)
+
+{       if (pi->private) {		/* turn off the power */
+		friq_connect(pi);
+		CMD(0x1d); CMD(0x1e);
+		friq_disconnect(pi);
+		pi->private = 0;
+	}
+
+	MOD_DEC_USE_COUNT;
+}
+
+struct pi_protocol friq = {"friq",0,5,2,1,1,
+                           friq_write_regr,
+                           friq_read_regr,
+                           friq_write_block,
+                           friq_read_block,
+                           friq_connect,
+                           friq_disconnect,
+                           0,
+                           0,
+                           friq_test_proto,
+                           friq_log_adapter,
+                           friq_init_proto,
+                           friq_release_proto
+                          };
+
+
+#ifdef MODULE
+
+int     init_module(void)
+
+{       return pi_register( &friq ) - 1;
+}
+
+void    cleanup_module(void)
+
+{       pi_unregister( &friq );
+}
+
+#endif
+
+/* end of friq.c */
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/frpw.c linux/drivers/block/paride/frpw.c
--- v2.1.131/linux/drivers/block/paride/frpw.c	Mon Oct  5 13:13:38 1998
+++ linux/drivers/block/paride/frpw.c	Tue Dec 22 08:29:00 1998
@@ -5,6 +5,12 @@
 	frpw.c is a low-level protocol driver for the Freecom "Power"
 	parallel port IDE adapter.
 	
+	Some applications of this adapter may require a "printer" reset
+	prior to loading the driver.  This can be done by loading and
+	unloading the "lp" driver, or it can be done by this driver
+	if you define FRPW_HARD_RESET.  The latter is not recommended
+	as it may upset devices on other ports.
+
 */
 
 /* Changes:
@@ -13,10 +19,11 @@
 			       fix chip detect
 			       added EPP-16 and EPP-32
 	1.02    GRG 1998.09.23 added hard reset to initialisation process
+	1.03    GRG 1998.12.14 made hard reset conditional
 
 */
 
-#define	FRPW_VERSION	"1.02" 
+#define	FRPW_VERSION	"1.03" 
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -185,8 +192,10 @@
 
 {	int olddelay, a, b;
 
+#ifdef FRPW_HARD_RESET
         w0(0); w2(8); udelay(50); w2(0xc);   /* parallel bus reset */
         mdelay(1500);
+#endif
 
 	olddelay = pi->delay;
 	pi->delay = 10;
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/jumbo linux/drivers/block/paride/jumbo
--- v2.1.131/linux/drivers/block/paride/jumbo	Mon Oct  5 13:13:38 1998
+++ linux/drivers/block/paride/jumbo	Tue Dec 22 08:29:00 1998
@@ -53,11 +53,11 @@
 FK="-D__KERNEL__ -I ../../../include"
 FLCH=-D_LINUX_CONFIG_H
 #
-echo cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
-cc $FK $FSMP $FLCH $FPARP $FPROTO -Wall -O2 -o Jb.o -c paride.c
+echo cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
+cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
 #
-echo cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
-cc $FK $FSMP -Wall -O2 -o Jp.o -c $PROTO.c
+echo cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
+cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
 #
 echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
 cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/on26.c linux/drivers/block/paride/on26.c
--- v2.1.131/linux/drivers/block/paride/on26.c	Mon Oct  5 13:13:38 1998
+++ linux/drivers/block/paride/on26.c	Tue Dec 22 08:29:00 1998
@@ -11,10 +11,12 @@
 
         1.01    GRG 1998.05.06 init_proto, release_proto
 	1.02    GRG 1998.09.23 updates for the -E rev chip
+	1.03    GRG 1998.12.14 fix for slave drives
+	1.04    GRG 1998.12.20 yet another bug fix
 
 */
 
-#define ON26_VERSION      "1.02"
+#define ON26_VERSION      "1.04"
 
 #include <linux/module.h>
 #include <linux/delay.h>
@@ -118,9 +120,11 @@
         w2(pi->saved_r2);
 } 
 
+#define	RESET_WAIT  200
+
 static int on26_test_port( PIA *pi)  /* hard reset */
 
-{       int     i, m, d;
+{       int     i, m, d, x, y;
 
         pi->saved_r0 = r0();
         pi->saved_r2 = r2();
@@ -151,11 +155,18 @@
             
             on26_write_regr(pi,0,6,0xa0);
 
-            for (i=0;i<100;i++) {
-                if (!(on26_read_regr(pi,0,7) & 0x80)) break;
-                udelay(100000);
+            for (i=0;i<RESET_WAIT;i++) {
+                on26_write_regr(pi,0,6,0xa0);
+                x = on26_read_regr(pi,0,7);
+                on26_write_regr(pi,0,6,0xb0);
+                y = on26_read_regr(pi,0,7);
+                if (!((x&0x80)||(y&0x80))) break;
+                mdelay(100);
             }
 
+	    if (i == RESET_WAIT) 
+		printk("on26: Device reset failed (%x,%x)\n",x,y);
+
             w0(4); P1; w0(4); P1;
         }
 
@@ -189,7 +200,7 @@
         case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
 		udelay(10);
                 for (k=0;k<count/2;k++) {
-                        w2(0x26); buf[2*k] = r0(); 
+                        w2(0x26); buf[2*k] = r0();  
 			w2(0x24); buf[2*k+1] = r0();
                 }
                 w0(2); P1; w0(9); P2;
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/paride.c linux/drivers/block/paride/paride.c
--- v2.1.131/linux/drivers/block/paride/paride.c	Wed Aug 26 11:37:35 1998
+++ linux/drivers/block/paride/paride.c	Tue Dec 22 08:29:00 1998
@@ -12,10 +12,11 @@
 	1.01	GRG 1998.05.03	Use spinlocks
 	1.02	GRG 1998.05.05  init_proto, release_proto, ktti
 	1.03	GRG 1998.08.15  eliminate compiler warning
+	1.04    GRG 1998.11.28  added support for FRIQ 
 
 */
 
-#define PI_VERSION      "1.03"
+#define PI_VERSION      "1.04"
 
 #include <linux/module.h>
 #include <linux/config.h>
@@ -450,6 +451,11 @@
           pi_register(&frpw);
         };
 #endif
+#ifdef CONFIG_PARIDE_FRIQ
+        { extern struct pi_protocol friq;
+          pi_register(&friq);
+        };
+#endif 
 #ifdef CONFIG_PARIDE_FIT2
         { extern struct pi_protocol fit2;
           pi_register(&fit2);
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/pseudo.h linux/drivers/block/paride/pseudo.h
--- v2.1.131/linux/drivers/block/paride/pseudo.h	Tue Jun 23 10:01:22 1998
+++ linux/drivers/block/paride/pseudo.h	Tue Dec 22 08:29:00 1998
@@ -16,19 +16,21 @@
 	when either it returns true, or timeout jiffies have passed,
 	continuation() will be invoked.
 
-	If nice is true, the test will done approximately once a
+	If nice is 1, the test will done approximately once a
 	jiffy.  If nice is 0, the test will also be done whenever
-	the scheduler runs (by adding it to a task queue).
+	the scheduler runs (by adding it to a task queue).  If
+	nice is greater than 1, the test will be done once every
+	(nice-1) jiffies. 
 
 */
 
 /* Changes:
 
 	1.01	1998.05.03	Switched from cli()/sti() to spinlocks
-
+	1.02    1998.12.14      Added support for nice > 1
 */
 	
-#define PS_VERSION	"1.01"
+#define PS_VERSION	"1.02"
 
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -37,13 +39,13 @@
 static void ps_timer_int( unsigned long data);
 static void ps_tq_int( void *data);
 
-static int ps_use_tq = 1;
 static void (* ps_continuation)(void);
 static int (* ps_ready)(void);
 static int ps_then;
 static int ps_timeout;
 static int ps_timer_active = 0;
 static int ps_tq_active = 0;
+static int ps_nice = 0;
 
 static spinlock_t ps_spinlock = SPIN_LOCK_UNLOCKED;
 
@@ -62,9 +64,9 @@
 	ps_ready = ready;
         ps_then = jiffies;
 	ps_timeout = jiffies + timeout;
-	ps_use_tq = !nice;
+	ps_nice = nice;
 
-        if (ps_use_tq && !ps_tq_active) {
+        if (!ps_nice && !ps_tq_active) {
 #ifdef HAVE_DISABLE_HLT
                 disable_hlt();
 #endif
@@ -74,7 +76,7 @@
 
         if (!ps_timer_active) {
 		ps_timer_active = 1;
-                ps_timer.expires = jiffies;
+                ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
                 add_timer(&ps_timer);
         }
 
@@ -136,7 +138,7 @@
 		return;
 		}
 	ps_timer_active = 1;
-        ps_timer.expires = jiffies;
+        ps_timer.expires = jiffies + ((ps_nice>0)?(ps_nice-1):0);
         add_timer(&ps_timer);
         spin_unlock_irqrestore(&ps_spinlock,flags);
 }
diff -u --recursive --new-file v2.1.131/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.1.131/linux/drivers/block/paride/pt.c	Sun Nov  8 14:02:51 1998
+++ linux/drivers/block/paride/pt.c	Tue Dec 22 08:29:00 1998
@@ -471,7 +471,7 @@
 
 {	int	k, e, s;
 
-	k = 0;
+	k = 0; e = 0; s = 0;
 	while (k < tmo) {
 		pt_sleep(pause);
 		k++;
diff -u --recursive --new-file v2.1.131/linux/drivers/block/raid1.c linux/drivers/block/raid1.c
--- v2.1.131/linux/drivers/block/raid1.c	Wed Jun 24 22:54:04 1998
+++ linux/drivers/block/raid1.c	Tue Dec 22 08:12:38 1998
@@ -309,8 +309,7 @@
 		mirror_bh [i]->b_dev        = bh->b_dev;
 		mirror_bh [i]->b_rdev 	    = raid_conf->mirrors [i].dev;
 		mirror_bh [i]->b_rsector    = bh->b_rsector;
-		mirror_bh [i]->b_state      =   (1<<BH_Req) | 
-						(1<<BH_Touched) | (1<<BH_Dirty);
+		mirror_bh [i]->b_state      = (1<<BH_Req) | (1<<BH_Dirty);
 		mirror_bh [i]->b_count      = 1;
 		mirror_bh [i]->b_size       = bh->b_size;
 		mirror_bh [i]->b_data       = bh->b_data;
diff -u --recursive --new-file v2.1.131/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c
--- v2.1.131/linux/drivers/block/z2ram.c	Wed Aug 26 11:37:36 1998
+++ linux/drivers/block/z2ram.c	Fri Dec 18 09:36:05 1998
@@ -14,6 +14,8 @@
 **          37     0       Use Zorro II and Chip ram
 **          37     1       Use only Zorro II ram
 **          37     2       Use only Chip ram
+**          37     4-7     Use memory list entry 1-4 (first is 0)
+** ++jskov: support for 1-4th memory list entry.
 **
 ** Permission to use, copy, modify, and distribute this software and its
 ** documentation for any purpose and without fee is hereby granted, provided
@@ -25,6 +27,7 @@
 
 #define MAJOR_NR    Z2RAM_MAJOR
 
+#include <linux/config.h>
 #include <linux/major.h>
 #include <linux/malloc.h>
 #include <linux/blk.h>
@@ -37,23 +40,37 @@
 #include <asm/setup.h>
 #include <asm/bitops.h>
 #include <asm/amigahw.h>
+#ifdef CONFIG_APUS
+#include <asm/pgtable.h>
+#include <asm/io.h>
+#endif
 #include <linux/zorro.h>
 
+
+extern int num_memory;
+extern struct mem_info memory[NUM_MEMINFO];
+
 #define TRUE                  (1)
 #define FALSE                 (0)
 
 #define Z2MINOR_COMBINED      (0)
 #define Z2MINOR_Z2ONLY        (1)
 #define Z2MINOR_CHIPONLY      (2)
+#define Z2MINOR_MEMLIST1      (4)
+#define Z2MINOR_MEMLIST2      (5)
+#define Z2MINOR_MEMLIST3      (6)
+#define Z2MINOR_MEMLIST4      (7)
+#define Z2MINOR_COUNT         (8) /* Move this down when adding a new minor */
 
 #define Z2RAM_CHUNK1024       ( Z2RAM_CHUNKSIZE >> 10 )
 
 static u_long *z2ram_map    = NULL;
 static u_long z2ram_size    = 0;
-static int z2_blocksizes[3] = { 1024, 1024, 1024 };
-static int z2_sizes[3]      = {    0,    0,    0 };
+static int z2_blocksizes[Z2MINOR_COUNT];
+static int z2_sizes[Z2MINOR_COUNT];
 static int z2_count         = 0;
 static int chip_count       = 0;
+static int list_count       = 0;
 static int current_device   = -1;
 
 static void
@@ -166,8 +183,61 @@
     {
 	z2_count   = 0;
 	chip_count = 0;
+	list_count = 0;
 	z2ram_size = 0;
 
+	/* Use a specific list entry. */
+	if (device >= Z2MINOR_MEMLIST1 && device <= Z2MINOR_MEMLIST4) {
+		int index = device - Z2MINOR_MEMLIST1 + 1;
+		unsigned long size, paddr, vaddr;
+
+		if (index >= num_memory) {
+			printk( KERN_ERR DEVICE_NAME
+				": no such entry in z2ram_map\n" );
+			return -ENOMEM;
+		}
+
+		paddr = memory[index].addr;
+		size = memory[index].size & ~(Z2RAM_CHUNKSIZE-1);
+
+#ifdef __powerpc__
+		/* FIXME: ioremap doesn't build correct memory tables. */
+		{
+			extern void* vmalloc (unsigned long);
+			extern void vfree (void*);
+			vfree(vmalloc (size));
+		}
+
+		vaddr = (unsigned long) __ioremap (paddr, size, 
+						   _PAGE_WRITETHRU);
+
+#else
+		vaddr = kernel_map (paddr, size, KERNELMAP_FULL_CACHING,
+				    NULL);
+#endif
+		z2ram_map = 
+			kmalloc((size/Z2RAM_CHUNKSIZE)*sizeof(z2ram_map[0]),
+				GFP_KERNEL);
+		if ( z2ram_map == NULL )
+		{
+		    printk( KERN_ERR DEVICE_NAME
+			": cannot get mem for z2ram_map\n" );
+		    return -ENOMEM;
+		}
+
+		while (size) {
+			z2ram_map[ z2ram_size++ ] = vaddr;
+			size -= Z2RAM_CHUNKSIZE;
+			vaddr += Z2RAM_CHUNKSIZE;
+			list_count++;
+		}
+
+		if ( z2ram_size != 0 )
+		    printk( KERN_INFO DEVICE_NAME
+			": using %iK List Entry %d Memory\n",
+			list_count * Z2RAM_CHUNK1024, index );
+	} else
+
 	switch ( device )
 	{
 	    case Z2MINOR_COMBINED:
@@ -253,12 +323,11 @@
     return 0;
 }
 
-static void 
+static int
 z2_release( struct inode *inode, struct file *filp )
 {
-
     if ( current_device == -1 )
-	return;     
+	return 0;     
 
     sync_dev( inode->i_rdev );
 
@@ -266,7 +335,7 @@
     MOD_DEC_USE_COUNT;
 #endif
 
-    return;
+    return 0;
 }
 
 static struct file_operations z2_fops =
@@ -281,7 +350,10 @@
 	z2_open,                /* open */
 	NULL,			/* flush */
 	z2_release,             /* release */
-	block_fsync             /* fsync */
+	block_fsync,            /* fsync */
+	NULL,			/* fasync */
+	NULL,			/* check_media_change */
+	NULL,			/* revalidate */
 };
 
 __initfunc(int
@@ -297,6 +369,16 @@
 	    MAJOR_NR );
 	return -EBUSY;
     }
+
+    {
+	    /* Initialize size arrays. */
+	    int i;
+
+	    for (i = 0; i < Z2MINOR_COUNT; i++) {
+		    z2_blocksizes[ i ] = 1024;
+		    z2_sizes[ i ] = 0;
+	    }
+    }    
    
     blk_dev[ MAJOR_NR ].request_fn = DEVICE_REQUEST;
     blksize_size[ MAJOR_NR ] = z2_blocksizes;
diff -u --recursive --new-file v2.1.131/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.1.131/linux/drivers/cdrom/cdu31a.c	Sun Nov  8 14:02:52 1998
+++ linux/drivers/cdrom/cdu31a.c	Sun Dec 20 04:36:47 1998
@@ -32,7 +32,7 @@
  * the following:
  *
  *   retry_count = jiffies+ SONY_JIFFIES_TIMEOUT;
- *   while ((retry_count > jiffies) && (! <some condition to wait for))
+ *   while (time_before(jiffies, retry_count) && (! <some condition to wait for))
  *   {
  *      while (handle_sony_cd_attention())
  *         ;
@@ -488,7 +488,7 @@
   reset_drive();
 
   retry_count = jiffies + SONY_RESET_TIMEOUT;
-  while ((retry_count > jiffies) && (!is_attention()))
+  while (time_before(jiffies, retry_count) && (!is_attention()))
   {
      sony_sleep();
   }
@@ -740,7 +740,7 @@
    printk("cdu31a: Resetting drive on error\n");
    reset_drive();
    retry_count = jiffies + SONY_RESET_TIMEOUT;
-   while ((retry_count > jiffies) && (!is_attention()))
+   while (time_before(jiffies, retry_count) && (!is_attention()))
    {
       sony_sleep();
    }
@@ -808,7 +808,7 @@
       ;
    /* Wait for the result data to be ready */
    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-   while ((retry_count > jiffies) && (is_busy() || (!(is_result_ready()))))
+   while (time_before(jiffies, retry_count) && (is_busy() || (!(is_result_ready()))))
    {
       sony_sleep();
 
@@ -978,7 +978,7 @@
    sti();
    
    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-   while ((retry_count > jiffies) && (is_busy()))
+   while (time_before(jiffies, retry_count) && (is_busy()))
    {
       sony_sleep();
       
@@ -1246,7 +1246,7 @@
       ;
 
    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-   while ((retry_count > jiffies) && (is_busy()))
+   while (time_before(jiffies, retry_count) && (is_busy()))
    {
       sony_sleep();
       
@@ -1514,7 +1514,7 @@
 
    /* Wait for the drive to tell us we have something */
    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-   while ((retry_count > jiffies) && !(is_data_ready()))
+   while (time_before(jiffies, retry_count) && !(is_data_ready()))
    {
       while (handle_sony_cd_attention())
          ;
@@ -1553,7 +1553,7 @@
 
       /* Wait for the status from the drive. */
       retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-      while ((retry_count > jiffies) && !(is_result_ready()))
+      while (time_before(jiffies, retry_count) && !(is_result_ready()))
       {
          while (handle_sony_cd_attention())
             ;
@@ -2432,8 +2432,7 @@
    /* Wait for the drive to tell us we have something */
    retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
 continue_read_audio_wait:
-   while (   (retry_count > jiffies)
-          && !(is_data_ready())
+   while (time_before(jiffies, retry_count) && !(is_data_ready())
           && !(is_result_ready() || result_read))
    {
       while (handle_sony_cd_attention())
@@ -2495,7 +2494,7 @@
       {
          /* Wait for the drive to tell us we have something */
          retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
-         while ((retry_count > jiffies) && !(is_result_ready()))
+         while (time_before(jiffies, retry_count) && !(is_result_ready()))
          {
             while (handle_sony_cd_attention())
                ;
@@ -3286,7 +3285,7 @@
        */
       reset_drive();
       retry_count = jiffies + SONY_RESET_TIMEOUT;
-      while ((retry_count > jiffies) && (!is_attention()))
+      while (time_before(jiffies, retry_count) && (!is_attention()))
       {
          sony_sleep();
       }
diff -u --recursive --new-file v2.1.131/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
--- v2.1.131/linux/drivers/cdrom/mcdx.c	Thu Nov 12 16:21:18 1998
+++ linux/drivers/cdrom/mcdx.c	Sun Dec 20 04:36:47 1998
@@ -1778,7 +1778,7 @@
     if (!buf) buf = &c;
 
     while (inb((unsigned int) stuffp->rreg_status) & MCDX_RBIT_STEN) {
-        if (jiffies > timeout) return -1;
+        if (time_after(jiffies, timeout)) return -1;
         mcdx_delay(stuffp, delay);
     }
 
diff -u --recursive --new-file v2.1.131/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.1.131/linux/drivers/cdrom/sbpcd.c	Sun Nov  8 14:02:52 1998
+++ linux/drivers/cdrom/sbpcd.c	Sun Dec 20 04:36:47 1998
@@ -1014,20 +1014,20 @@
               {
               case 4:
                 sbp_sleep(HZ);
-                if (jiffies > timeout_4) gear++;
+                if (time_after(jiffies, timeout_4)) gear++;
                 msg(DBG_TEA, "CDi_stat_loop_T: long sleep active.\n");
                 break;
               case 3:
                 sbp_sleep(HZ/10);
-                if (jiffies > timeout_3) gear++;
+                if (time_after(jiffies, timeout_3)) gear++;
                 break;
               case 2:
                 sbp_sleep(HZ/100);
-                if (jiffies > timeout_2) gear++;
+                if (time_after(jiffies, timeout_2)) gear++;
                 break;
               case 1:
                 sbp_sleep(0);
-                if (jiffies > timeout_1) gear++;
+                if (time_after(jiffies, timeout_1)) gear++;
               }
           } while (gear < 5);
 	return -1;
@@ -1037,7 +1037,7 @@
 {
 	int i,j;
 	
-	for(timeout = jiffies + 10*HZ, i=maxtim_data; timeout > jiffies; )
+	for(timeout = jiffies + 10*HZ, i=maxtim_data; time_before(jiffies, timeout); )
 	{
 		for ( ;i!=0;i--)
 		{
@@ -1098,11 +1098,11 @@
 				st=inb(CDi_status);
 				if (!(st&s_not_result_ready)) break;
 			}
-			if ((j!=0)||(timeout<=jiffies)) break;
+			if ((j!=0)||time_after_eq(jiffies, timeout)) break;
 			sbp_sleep(1);
 			j = 1;
 		}
-		if (timeout<=jiffies) break;
+		if (time_after_eq(jiffies, timeout)) break;
 		infobuf[i]=inb(CDi_info);
 	}
 #if 000
@@ -1238,7 +1238,7 @@
 			i=inb(CDi_status);
 			if (!(i&s_not_result_ready)) break;
 		}
-		if ((j!=0)||(timeout<jiffies)) break;
+		if ((j!=0)||time_after(jiffies, timeout)) break;
 		sbp_sleep(1);
 		j = 1;
 	}
@@ -4355,7 +4355,7 @@
 						if (!(j&s_not_result_ready)) break;
 						if (fam0L_drive) if (j&s_attention) break;
 					}
-					if (try != 0 || timeout <= jiffies) break;
+					if (try != 0 || time_after_eq(jiffies, timeout)) break;
 					if (data_retrying == 0) data_waits++;
 					data_retrying = 1;
 					sbp_sleep(1);
@@ -4419,7 +4419,7 @@
 			if (fam0L_drive)
 			{
 				i=maxtim_data;
-				for (timeout=jiffies+9*HZ; timeout > jiffies; timeout--)
+				for (timeout=jiffies+9*HZ; time_before(jiffies, timeout); timeout--)
 				{
 					for ( ;i!=0;i--)
 					{
@@ -4428,7 +4428,7 @@
 						if (!(j&s_not_result_ready)) break;
 						if (j&s_attention) break;
 					}
-					if (i != 0 || timeout <= jiffies) break;
+					if (i != 0 || time_after_eq(jiffies, timeout)) break;
 					sbp_sleep(0);
 					i = 1;
 				}
@@ -5250,7 +5250,7 @@
 	{
 		SBPCD_CLI;
 		i=maxtim_data;
-		for (timeout=jiffies+HZ; timeout > jiffies; timeout--)
+		for (timeout=jiffies+HZ; time_before(jiffies, timeout); timeout--)
 		{
 			for ( ;i!=0;i--)
 			{
@@ -5259,7 +5259,7 @@
 				if (!(j&s_not_result_ready)) break;
 				if (j&s_attention) break;
 			}
-			if (i != 0 || timeout <= jiffies) break;
+			if (i != 0 || time_after_eq(jiffies, timeout)) break;
 			sbp_sleep(0);
 			i = 1;
 		}
@@ -5701,7 +5701,7 @@
 				if (i<0) break;
 				if (!st_caddy_in) break;
 				}
-			while ((!st_diskok)||(timeout<jiffies));
+			while ((!st_diskok)||time_after(jiffies, timeout));
 		}
 		i=SetSpeed();
 		if (i>=0) D_S[j].CD_changed=1;
diff -u --recursive --new-file v2.1.131/linux/drivers/cdrom/sjcd.c linux/drivers/cdrom/sjcd.c
--- v2.1.131/linux/drivers/cdrom/sjcd.c	Wed Aug 26 11:37:36 1998
+++ linux/drivers/cdrom/sjcd.c	Sun Dec 20 04:36:47 1998
@@ -1488,7 +1488,7 @@
     /*
      * Wait 10ms approx.
      */
-    for( timer = jiffies; jiffies <= timer; );
+    for( timer = jiffies; time_before_eq(jiffies, timer); );
     if ( (i % 100) == 0 ) printk( "." );
     ( void )sjcd_check_status();
   }
@@ -1509,7 +1509,7 @@
     /*
      * Wait 10ms approx.
      */
-    for( timer = jiffies; jiffies <= timer; );
+    for( timer = jiffies; time_before_eq(jiffies, timer); );
     if ( (i % 100) == 0 ) printk( "." );
     ( void )sjcd_check_status();
   }
@@ -1540,7 +1540,7 @@
       /*
        * Wait 10ms approx.
        */
-      for( timer = jiffies; jiffies <= timer; );
+      for( timer = jiffies; time_before_eq(jiffies, timer); );
       if ( (i % 100) == 0 ) printk( "." );
       ( void )sjcd_check_status();
     }
diff -u --recursive --new-file v2.1.131/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.1.131/linux/drivers/char/Config.in	Fri Oct 23 22:01:20 1998
+++ linux/drivers/char/Config.in	Wed Dec 16 12:53:13 1998
@@ -35,10 +35,13 @@
    fi
    tristate 'SDL RISCom/8 card support' CONFIG_RISCOM8
    tristate 'Specialix IO8+ card support' CONFIG_SPECIALIX
-   if [ "$CONFIG_SPECIALIX" = "y" -o  "$CONFIG_SPECIALIX" = "m" ]; then
+   if [ "$CONFIG_SPECIALIX" != "n" ]; then
      bool 'Specialix DTR/RTS pin is RTS' CONFIG_SPECIALIX_RTSCTS
    fi 
    tristate 'Hayes ESP serial port support' CONFIG_ESPSERIAL
+   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	dep_tristate 'Multi-Tech multiport card support' CONFIG_ISI m
+   fi
 fi
 bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
 if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
@@ -107,10 +110,12 @@
     hex '  Aztech/Packard Bell I/O port (0x350 or 0x358)' CONFIG_RADIO_AZTECH_PORT 350
   fi
   dep_tristate 'Miro PCM20 Radio' CONFIG_RADIO_MIROPCM20 $CONFIG_VIDEO_DEV
-  dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+  if [ "$CONFIG_PCI" != "n" ]; then
+    dep_tristate 'BT848 Video For Linux' CONFIG_VIDEO_BT848 $CONFIG_VIDEO_DEV
+  fi
   if [ "$CONFIG_PARPORT" != "n" ]; then
-    dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV
-    dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV
+    dep_tristate 'Quickcam BW Video For Linux' CONFIG_VIDEO_BWQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
+    dep_tristate 'Colour QuickCam Video For Linux (EXPERIMENTAL)' CONFIG_VIDEO_CQCAM $CONFIG_VIDEO_DEV $CONFIG_PARPORT
   fi
   dep_tristate 'Mediavision Pro Movie Studio Video For Linux' CONFIG_VIDEO_PMS $CONFIG_VIDEO_DEV
   dep_tristate 'SAA5249 Teletext processor' CONFIG_VIDEO_SAA5249 $CONFIG_VIDEO_DEV
diff -u --recursive --new-file v2.1.131/linux/drivers/char/Makefile linux/drivers/char/Makefile
--- v2.1.131/linux/drivers/char/Makefile	Thu Nov 19 09:56:28 1998
+++ linux/drivers/char/Makefile	Wed Dec 16 12:53:13 1998
@@ -118,6 +118,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_ISI),y)
+L_OBJS += isicom.o
+else
+  ifeq ($(CONFIG_ISI),m)
+  M_OBJS += isicom.o
+  endif
+endif
+
 ifeq ($(CONFIG_ESPSERIAL),y)
 L_OBJS += esp.o
 else
diff -u --recursive --new-file v2.1.131/linux/drivers/char/bttv.c linux/drivers/char/bttv.c
--- v2.1.131/linux/drivers/char/bttv.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/char/bttv.c	Wed Dec 16 12:53:13 1998
@@ -31,7 +31,7 @@
     * fix RAW Composite grabbing for NTSC 
     * fix VBI reading double frames when grabbing is active
     * allow for different VDELAYs
-    * extra modules for tda9850, tda8425, any volunteers???
+    * handle tda8425 properly
 */
 
 #include <linux/module.h>
@@ -98,7 +98,8 @@
 static struct bttv bttvs[BTTV_MAX];
 
 #define I2C_TIMING (0x7<<4)
-#define I2C_DELAY   10
+#define I2C_DELAY   50		/* Was 10 - some reports that more is needed
+				   regardless of what the spec says */
 #define I2C_SET(CTRL,DATA) \
     { btwrite((CTRL<<1)|(DATA), BT848_I2C); udelay(I2C_DELAY); }
 #define I2C_GET()   (btread(BT848_I2C)&1)
@@ -1460,6 +1461,12 @@
 			v.rangelow=0;
 			v.rangehigh=0xFFFFFFFF;
 			v.flags=VIDEO_TUNER_PAL|VIDEO_TUNER_NTSC|VIDEO_TUNER_SECAM;
+			if (btv->audio_chip == TDA9850) {
+				unsigned char ALR1;
+				ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
+				if (ALR1 & 32)
+					v.flags |= VIDEO_TUNER_STEREO_ON;
+			}
 			v.mode = btv->win.norm;
 			v.signal = (btread(BT848_DSTATUS)&BT848_DSTATUS_HLOC) ? 0xFFFF : 0;
 			if(copy_to_user(arg,&v,sizeof(v)))
@@ -1687,8 +1694,17 @@
 			v.flags&=~(VIDEO_AUDIO_MUTE|VIDEO_AUDIO_MUTABLE);
 			v.flags|=VIDEO_AUDIO_MUTABLE;
 			strcpy(v.name,"TV");
-			if (btv->have_msp3400) 
-			{
+			if (btv->audio_chip == TDA9850) {
+				unsigned char ALR1;
+				v.flags|=VIDEO_AUDIO_VOLUME;
+				ALR1 = I2CRead(&(btv->i2c), I2C_TDA9850|1);
+				v.mode = VIDEO_SOUND_MONO;
+				v.mode |= (ALR1 & 32) ? VIDEO_SOUND_STEREO:0;
+				v.mode |= (ALR1 & 32) ? VIDEO_SOUND_LANG1:0;
+				v.volume = 32768;       /* fixme */
+				v.step = 4096;
+			}
+			else if (btv->have_msp3400) {
                                 v.flags|=VIDEO_AUDIO_VOLUME |
                                 	VIDEO_AUDIO_BASS |
                                 	VIDEO_AUDIO_TREBLE;
@@ -1726,8 +1742,20 @@
 			bt848_muxsel(btv,v.audio);
 			if(!(v.flags&VIDEO_AUDIO_MUTE))
 				audio(btv, AUDIO_UNMUTE);
-			if (btv->have_msp3400) 
-			{
+			if (btv->audio_chip == TDA9850) {
+				unsigned char con3 = 0;
+				if (v.mode & VIDEO_SOUND_LANG1)
+					con3 = 0x80;	/* sap */
+				if (v.mode & VIDEO_SOUND_STEREO)
+					con3 = 0x40;	/* stereo */
+				I2CWrite(&(btv->i2c), I2C_TDA9850,
+					TDA9850_CON3, con3, 1);
+				if (v.flags & VIDEO_AUDIO_VOLUME)
+					I2CWrite(&(btv->i2c), I2C_TDA9850,
+						TDA9850_CON4,
+						(v.volume>>12) & 15, 1);
+			}
+			else if (btv->have_msp3400) {
                                 i2c_control_device(&(btv->i2c),
                                                 I2C_DRIVERID_MSP3400,
                                                 MSP_SET_VOLUME,&(v.volume));
@@ -2389,7 +2417,11 @@
     
 		if (I2CRead(&(btv->i2c), I2C_HAUPEE)>=0) {
 			if(btv->id>849)
+			{
 				btv->type=BTTV_HAUPPAUGE878;
+				btv->pll.pll_ifreq = 28636363;
+				btv->pll.pll_crystal = BT848_IFORM_XT0;
+			}
 			else
 				btv->type=BTTV_HAUPPAUGE;
 		}
@@ -2397,7 +2429,7 @@
 		        if (I2CRead(&(btv->i2c), I2C_STBEE)>=0)
 			        btv->type=BTTV_STB;
 
-                if (btv->type == BTTV_MIRO) {
+                if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
                         /* auto detect tuner for MIRO cards */
                         btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
                 }
@@ -2582,10 +2614,13 @@
 	btv->grabcount=0;
 	btv->grab=0;
 	btv->lastgrab=0;
-	btv->field=btv->last_field=0;
-	btv->video_dev.minor = -1;
-	btv->vbi_dev.minor = -1;
-	btv->radio_dev.minor = -1;
+        btv->field=btv->last_field=0;
+        /* cevans - prevents panic if initialization bails due to memory
+         * alloc failures!
+         */
+        btv->video_dev.minor = -1;
+        btv->vbi_dev.minor = -1;
+        btv->radio_dev.minor = -1;
 
 	/* i2c */
 	memcpy(&(btv->i2c),&bttv_i2c_bus_template,sizeof(struct i2c_bus));
diff -u --recursive --new-file v2.1.131/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.1.131/linux/drivers/char/busmouse.c	Wed Aug 26 11:37:36 1998
+++ linux/drivers/char/busmouse.c	Wed Dec 16 13:38:18 1998
@@ -56,6 +56,10 @@
 static struct mouse_status mouse;
 static int mouse_irq = MOUSE_IRQ;
 
+#ifdef MODULE
+MODULE_PARM(mouse_irq, "i");
+#endif
+
 __initfunc(void bmouse_setup(char *str, int *ints))
 {
 	if (ints[0] > 0)
diff -u --recursive --new-file v2.1.131/linux/drivers/char/c-qcam.c linux/drivers/char/c-qcam.c
--- v2.1.131/linux/drivers/char/c-qcam.c	Sun Nov  8 14:02:53 1998
+++ linux/drivers/char/c-qcam.c	Wed Dec 16 12:53:13 1998
@@ -1,13 +1,9 @@
 /*
- *	Video4Linux: Colour QuickCam driver
+ *	Video4Linux Colour QuickCam driver
+ *	Copyright 1997-1998 Philip Blundell <philb@gnu.org>
  *
- *	Philip Blundell <philb@gnu.org>, December 30 1997
- *
- *	Largely untested (seems to work at 24bpp with a bidirectional port,
- *	though). 
  */
 
-
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -22,27 +18,47 @@
 #include <linux/videodev.h>
 #include <asm/uaccess.h>
 
-#include "c-qcam.h"
+struct qcam_device {
+	struct video_device vdev;
+	struct pardevice *pdev;
+	struct parport *pport;
+	int width, height;
+	int ccd_width, ccd_height;
+	int mode;
+	int contrast, brightness, whitebal;
+	int top, left;
+	unsigned int bidirectional;
+};
+
+/* The three possible QuickCam modes */
+#define QC_MILLIONS	0x18
+#define QC_BILLIONS	0x10
+#define QC_THOUSANDS	0x08	/* with VIDEC compression (not supported) */
+
+/* The three possible decimations */
+#define QC_DECIMATION_1		0
+#define QC_DECIMATION_2		2
+#define QC_DECIMATION_4		4
 
-static __inline__ void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
+static inline void qcam_set_ack(struct qcam_device *qcam, unsigned int i)
 {
 	/* note: the QC specs refer to the PCAck pin by voltage, not
 	   software level.  PC ports have builtin inverters. */
 	parport_frob_control(qcam->pport, 8, i?8:0);
 }
 
-static __inline__ unsigned int qcam_ready1(struct qcam_device *qcam)
+static inline unsigned int qcam_ready1(struct qcam_device *qcam)
 {
 	return (parport_read_status(qcam->pport) & 0x8)?1:0;
-
 }
 
-static __inline__ unsigned int qcam_ready2(struct qcam_device *qcam)
+static inline unsigned int qcam_ready2(struct qcam_device *qcam)
 {
 	return (parport_read_data(qcam->pport) & 0x1)?1:0;
 }
 
-static inline unsigned int qcam_await_ready1(struct qcam_device *qcam, int value)
+static unsigned int qcam_await_ready1(struct qcam_device *qcam, 
+					     int value)
 {
 	unsigned long oldjiffies = jiffies;
 	unsigned int i;
@@ -68,7 +84,7 @@
 	return 1;
 }
 
-static inline unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
+static unsigned int qcam_await_ready2(struct qcam_device *qcam, int value)
 {
 	unsigned long oldjiffies = jiffies;
 	unsigned int i;
@@ -95,7 +111,7 @@
 	return 1;
 }
 
-static inline int qcam_read_data(struct qcam_device *qcam)
+static int qcam_read_data(struct qcam_device *qcam)
 {
 	unsigned int idata;
 	qcam_set_ack(qcam, 0);
@@ -179,11 +195,10 @@
 	/* Set the brightness.  */
        	qcam_set(q, 11, q->brightness);
 
-	/* Set the height.  */
-	qcam_set(q, 17, q->height);
-
-	/* Set the width.  */
-	qcam_set(q, 19, q->width/2);
+	/* Set the height and width.  These refer to the actual
+	   CCD area *before* applying the selected decimation.  */
+	qcam_set(q, 17, q->ccd_height);
+	qcam_set(q, 19, q->ccd_width / 2);
 
 	/* Set top and left.  */
 	qcam_set(q, 0xd, q->top);
@@ -236,53 +251,24 @@
 			if (qcam_await_ready1(q, 0)) return bytes;
 			lo = (parport_read_status(q->pport) & 0xf0);
 			qcam_set_ack(q, 0);
-			/* flip some bits; cqcam gets this wrong */
-			buf[bytes++] = (hi | lo) ^ 0x88;
+			/* flip some bits */
+			buf[bytes++] = (hi | (lo >> 4)) ^ 0x88;
 		}
 	}
 	return bytes;
 }
 
-/* Convert the data the camera gives us into the desired output format. 
-   At the moment this is a no-op because read_bytes() does all the 
-   required stuff, for 24bpp at least.  */
-static size_t qcam_munge_buffer(struct qcam_device *q, char *inbuf, size_t inlen, char *outbuf, size_t outlen)
-{
-	size_t outptr = 0;
-	switch (q->bpp)
-	{
-	case 24:
-		while (inlen && (outptr <= (outlen-3)))
-		{
-			unsigned char r, g, b;
-			r = inbuf[0];
-			g = inbuf[1];
-			b = inbuf[2];
-			put_user(r, outbuf+(outptr++));
-			put_user(g, outbuf+(outptr++));
-			put_user(b, outbuf+(outptr++));
-			inlen -= 3;
-			inbuf += 3;
-		}
-		break;
-	default:
-		printk("c-qcam: can't convert this format (%d).\n", q->bpp);
-		return 0;
-	}
-	return outptr;
-}
+#define BUFSZ	150
 
 static long qc_capture(struct qcam_device *q, char *buf, unsigned long len)
 {
-	unsigned int tbpp = 0, tdecimation = 0, lines, pixelsperline, bitsperxfer;
+	unsigned lines, pixelsperline, bitsperxfer;
 	unsigned int is_bi_dir = q->bidirectional;
 	size_t wantlen, outptr = 0;
-	char *tmpbuf = kmalloc(768, GFP_KERNEL);
-	if (tmpbuf == NULL)
-	{
-		printk(KERN_ERR "cqcam: couldn't allocate a buffer.\n");
-		return -ENOMEM;
-	}
+	char tmpbuf[BUFSZ];
+
+	if (verify_area(VERIFY_WRITE, buf, len))
+		return -EFAULT;
 
 	/* Wait for camera to become ready */
 	for (;;)
@@ -290,33 +276,19 @@
 		int i = qcam_get(q, 41);
 		if (i == -1) {
 			qc_setup(q);
-			kfree(tmpbuf);
 			return -EIO;
 		}
-		if (i & 0x80)
-			schedule();
-		else
+		if ((i & 0x80) == 0)
 			break;
+		else
+			schedule();
 	}
 
-	switch (q->bpp) 
-	{
-	case 24: tbpp = QC_24BPP; break;
-	case 32: tbpp = QC_32BPP; break;
-	case 16: tbpp = QC_16BPP; break;
-	default: printk("qcam: Bad bpp.\n");
-	}
-	switch (q->transfer_scale) {
-	case 1: tdecimation = QC_1_1; break;
-	case 2: tdecimation = QC_2_1; break;
-	case 4: tdecimation = QC_4_1; break;
-	default: printk("qcam: Bad decimation.\n");
-	}
-	
-	qcam_set(q, 7, (tbpp | tdecimation) + ((is_bi_dir)?1:0) + 1);
+	if (qcam_set(q, 7, (q->mode | (is_bi_dir?1:0)) + 1))
+		return -EIO;
 	
-	lines = q->height / q->transfer_scale;
-	pixelsperline = q->width / q->transfer_scale;
+	lines = q->height;
+	pixelsperline = q->width;
 	bitsperxfer = (is_bi_dir) ? 24 : 8;
 
 	if (is_bi_dir)
@@ -326,33 +298,33 @@
 		mdelay(3);
 		qcam_set_ack(q, 0);
 		if (qcam_await_ready1(q, 1)) {
-			kfree(tmpbuf);
 			qc_setup(q);
 			return -EIO;
 		}
 		qcam_set_ack(q, 1);
 		if (qcam_await_ready1(q, 0)) {
-			kfree(tmpbuf);
 			qc_setup(q);
 			return -EIO;
 		}
 	}
 
-	wantlen = lines * pixelsperline * q->bpp / 8;
+	wantlen = lines * pixelsperline * 24 / 8;
 
 	while (wantlen)
 	{
-		size_t t, s, o;
-		s = (wantlen > 768)?768:wantlen;
+		size_t t, s;
+		s = (wantlen > BUFSZ)?BUFSZ:wantlen;
 		t = qcam_read_bytes(q, tmpbuf, s);
 		if (outptr < len)
 		{
-			o = qcam_munge_buffer(q, tmpbuf, t, buf + outptr, 
-					      len - outptr);
-			outptr += o;
+			size_t sz = len - outptr;
+			if (sz > t) sz = t;
+			if (__copy_to_user(buf+outptr, tmpbuf, sz))
+				break;
+			outptr += sz;
 		}
 		wantlen -= t;
-		if (t < s) 
+		if (t < s)
 			break;
 		if (current->need_resched)
 			schedule();
@@ -366,7 +338,6 @@
 		if (is_bi_dir)
 			parport_frob_control(q->pport, 0x20, 0);
 		qc_setup(q);
-		kfree(tmpbuf);
 		return len;
 	}
 
@@ -386,7 +357,6 @@
 			printk("qcam: no ack after EOF\n");
 			parport_frob_control(q->pport, 0x20, 0);
 			qc_setup(q);
-			kfree(tmpbuf);
 			return len;
 		}
 		parport_frob_control(q->pport, 0x20, 0);
@@ -396,7 +366,6 @@
 		{
 			printk("qcam: no ack to port turnaround\n");
 			qc_setup(q);
-			kfree(tmpbuf);
 			return len;
 		}
 	}
@@ -413,10 +382,7 @@
 			printk("qcam: bad EOF\n");
 	}
 
-	kfree(tmpbuf);
-
 	qcam_write_data(q, 0);
-
 	return len;
 }
 
@@ -526,7 +492,7 @@
 			p.brightness=qcam->brightness<<8;
 			p.contrast=qcam->contrast<<8;
 			p.whiteness=qcam->whitebal<<8;
-			p.depth=qcam->bpp;
+			p.depth=24;
 			p.palette=VIDEO_PALETTE_RGB24;
 			if(copy_to_user(arg, &p, sizeof(p)))
 				return -EFAULT;
@@ -538,7 +504,10 @@
 			if(copy_from_user(&p, arg, sizeof(p)))
 				return -EFAULT;
 
-			if (p.palette != VIDEO_PALETTE_RGB24)
+			/*
+			 *	Sanity check args
+			 */
+			if (p.depth != 24 || p.palette != VIDEO_PALETTE_RGB24)
 				return -EINVAL;
 			
 			/*
@@ -547,7 +516,6 @@
 			qcam->brightness = p.brightness>>8;
 			qcam->contrast = p.contrast>>8;
 			qcam->whitebal = p.whiteness>>8;
-			qcam->bpp = p.depth;
 			
 			parport_claim_or_block(qcam->pdev);
 			qc_setup(qcam); 
@@ -557,6 +525,7 @@
 		case VIDIOCSWIN:
 		{
 			struct video_window vw;
+
 			if(copy_from_user(&vw, arg,sizeof(vw)))
 				return -EFAULT;
 			if(vw.flags)
@@ -568,21 +537,33 @@
 			if(vw.width<80||vw.width>320)
 				return -EINVAL;
 				
-			qcam->width = 320;
-			qcam->height = 240;
-			qcam->transfer_scale = 4;
+			qcam->width = 80;
+			qcam->height = 60;
+			qcam->mode = QC_DECIMATION_4;
 			
 			if(vw.width>=160 && vw.height>=120)
 			{
-				qcam->transfer_scale = 2;
+				qcam->width = 160;
+				qcam->height = 120;
+				qcam->mode = QC_DECIMATION_2;
 			}
 			if(vw.width>=320 && vw.height>=240)
 			{
 				qcam->width = 320;
 				qcam->height = 240;
-				qcam->transfer_scale = 1;
+				qcam->mode = QC_DECIMATION_1;
+			}
+			qcam->mode |= QC_MILLIONS;
+#if 0
+			if(vw.width>=640 && vw.height>=480)
+			{
+				qcam->width = 640;
+				qcam->height = 480;
+				qcam->mode = QC_BILLIONS | QC_DECIMATION_1;
 			}
-			/* Ok we figured out what to use from our wide choice */
+#endif
+			/* Ok we figured out what to use from our 
+			   wide choice */
 			parport_claim_or_block(qcam->pdev);
 			qc_setup(qcam);
 			parport_release(qcam->pdev);
@@ -593,8 +574,8 @@
 			struct video_window vw;
 			vw.x=0;
 			vw.y=0;
-			vw.width=qcam->width/qcam->transfer_scale;
-			vw.height=qcam->height/qcam->transfer_scale;
+			vw.width=qcam->width;
+			vw.height=qcam->height;
 			vw.chromakey=0;
 			vw.flags=0;
 			if(copy_to_user(arg, &vw, sizeof(vw)))
@@ -677,10 +658,9 @@
 	
 	memcpy(&q->vdev, &qcam_template, sizeof(qcam_template));
 
-	q->width = 320;
-	q->height = 240;
-	q->bpp = 32;
-	q->transfer_scale = 1;
+	q->width = q->ccd_width = 320;
+	q->height = q->ccd_height = 240;
+	q->mode = QC_MILLIONS | QC_DECIMATION_1;
 	q->contrast = 192;
 	q->brightness = 240;
 	q->whitebal = 128;
@@ -723,7 +703,7 @@
 
 	parport_release(qcam->pdev);
 	
-	printk(KERN_INFO "Connectix Colour Quickcam on %s\n", 
+	printk(KERN_INFO "Colour Quickcam found on %s\n", 
 	       qcam->pport->name);
 	
 	if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER)==-1)
@@ -745,11 +725,15 @@
 	kfree(qcam);
 }
 
+#define BANNER "Connectix Colour Quickcam driver v0.02\n"
+
 #ifdef MODULE
 int init_module(void)
 {
 	struct parport *port;
 
+	printk(BANNER);
+
 	for (port = parport_enumerate(); port; port=port->next)
 		init_cqcam(port);
 
@@ -766,6 +750,8 @@
 __initfunc(int init_colour_qcams(struct video_init *unused))
 {
 	struct parport *port;
+
+	printk(BANNER);
 
 	for (port = parport_enumerate(); port; port=port->next)
 		init_cqcam(port);
diff -u --recursive --new-file v2.1.131/linux/drivers/char/c-qcam.h linux/drivers/char/c-qcam.h
--- v2.1.131/linux/drivers/char/c-qcam.h	Mon Jan 12 14:46:16 1998
+++ linux/drivers/char/c-qcam.h	Wed Dec 31 16:00:00 1969
@@ -1,18 +0,0 @@
-struct qcam_device {
-	struct video_device vdev;
-	struct pardevice *pdev;
-	struct parport *pport;
-	int width, height;
-	int bpp;
-	int contrast, brightness, whitebal;
-	int transfer_scale;
-	int top, left;
-	unsigned int bidirectional;
-};
-
-#define QC_1_1 0
-#define QC_2_1 2
-#define QC_4_1 4
-#define QC_16BPP 8
-#define QC_32BPP 16
-#define QC_24BPP 24
diff -u --recursive --new-file v2.1.131/linux/drivers/char/isicom.c linux/drivers/char/isicom.c
--- v2.1.131/linux/drivers/char/isicom.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/char/isicom.c	Wed Dec 16 12:53:13 1998
@@ -0,0 +1,1951 @@
+/*
+ *	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.
+ *
+ *	Original driver code supplied by Multi-Tech
+ *
+ *	Changes
+ *	1/9/98	alan@redhat.com		Merge to 2.0.x kernel tree
+ *					Obtain and use official major/minors
+ *					Loader switched to a misc device
+ *					(fixed range check bug as a side effect)
+ *					Printk clean up
+ *	9/12/98	alan@redhat.com		Rough port to 2.1.x
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/termios.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/serial.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#include <linux/isicom.h>
+
+static int isicom_refcount = 0;
+static int prev_card = 3;	/*	start servicing isi_card[0]	*/
+static struct isi_board * irq_to_board[16] = { NULL, };
+static struct tty_driver isicom_normal, isicom_callout;
+static struct tty_struct * isicom_table[PORT_COUNT] = { NULL, };
+static struct termios * isicom_termios[PORT_COUNT] = { NULL, };
+static struct termios * isicom_termios_locked[PORT_COUNT] = { NULL, };
+
+static struct isi_board isi_card[BOARD_COUNT];
+static struct isi_port  isi_ports[PORT_COUNT];
+
+DECLARE_TASK_QUEUE(tq_isicom);
+
+static struct timer_list tx;
+static char re_schedule = 1;
+#ifdef ISICOM_DEBUG
+static unsigned long tx_count = 0;
+#endif
+
+static int ISILoad_open(struct inode *inode, struct file *filp);
+static int ISILoad_release(struct inode *inode, struct file *filp);
+static int ISILoad_ioctl(struct inode *inode, struct file *filp, unsigned  int cmd, unsigned long arg);
+
+static void isicom_tx(unsigned long _data);
+static void isicom_start(struct tty_struct * tty);
+
+static unsigned char * tmp_buf = 0;
+static struct semaphore tmp_buf_sem = MUTEX;
+
+/*   baud index mappings from linux defns to isi */
+
+static char linuxb_to_isib[] = {
+	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17,     
+	18, 19
+};
+
+/* 
+ *  Firmware loader driver specific routines
+ *
+ */
+
+static struct file_operations ISILoad_fops = {
+	NULL,	/*	lseek	*/
+	NULL,	/*	read	*/
+	NULL,	/*	write	*/
+	NULL,	/*	readdir	*/
+	NULL,	/*	select	*/
+	ISILoad_ioctl,
+	NULL,	/*	mmap	*/
+	ISILoad_open,
+	NULL,	/*	flush	*/
+	ISILoad_release,
+	NULL,	/*	fsync	*/
+	NULL,	/*	fasync	*/
+	NULL,	/*	check_media_change	*/
+	NULL,	/*	revalidate	*/
+};
+
+struct miscdevice isiloader_device = {
+	ISILOAD_MISC_MINOR, "isictl", &ISILoad_fops
+};
+
+ 
+extern inline int WaitTillCardIsFree(unsigned short base)
+{
+	unsigned long count=0;
+	while( (!(inw(base+0xe) & 0x1)) && (count++ < 6000000));
+	if (inw(base+0xe)&0x1)  
+		return 0;
+	else
+		return 1;
+}
+
+static int ISILoad_open(struct inode *inode, struct file *filp)
+{
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISILoad:Firmware loader Opened!!!\n");
+#endif	
+	return 0;
+}
+
+static int ISILoad_release(struct inode *inode, struct file *filp)
+{
+#ifdef ISICOM_DEBUG
+	printk(KERN_DEBUG "ISILoad:Firmware loader Close(Release)d\n",);
+#endif	
+	return 0;
+}
+
+static int ISILoad_ioctl(struct inode *inode, struct file *filp,
+		         unsigned int cmd, unsigned long arg)
+{
+	unsigned int card, i, j, signature, status;
+	unsigned short word_count, base;
+	bin_frame frame;
+	/* exec_record exec_rec; */
+	
+	if(get_user(card, (int *)arg))
+		return -EFAULT;
+		
+	if(card < 0 || card >= BOARD_COUNT)
+		return -ENXIO;
+		
+	base=isi_card[card].base;
+	
+	if(base==0)
+		return -ENXIO;	/* disabled or not used */
+	
+	switch(cmd) {
+		case MIOCTL_RESET_CARD:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+			printk(KERN_DEBUG "ISILoad:Resetting Card%d at 0x%x ",card+1,base);
+								
+			inw(base+0x8);
+			
+			for(i=jiffies+HZ/100;i>jiffies;);
+				
+			outw(0,base+0x8); /* Reset */
+			
+			for(j=1;j<=3;j++) {
+				for(i=jiffies+HZ;i>jiffies;);
+				printk(".");
+			}	
+			signature=(inw(base+0x4)) & 0xff;	
+				
+			if (!(inw(base+0xe) & 0x1) || (inw(base+0x2))) {
+#ifdef ISICOM_DEBUG				
+				printk("\nbase+0x2=0x%x , base+0xe=0x%x",inw(base+0x2),inw(base+0xe));
+#endif				
+				printk("\nISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+				return -EIO;					
+			}
+				
+			switch(signature) {
+			case	0xa5:
+			case	0xbb:
+			case	0xdd:	isi_card[card].port_count = 8;
+				     	isi_card[card].shift_count = 12;
+				     	break;
+				        
+			case	0xcc:	isi_card[card].port_count = 16;
+					isi_card[card].shift_count = 11;
+					break;  			
+					
+			default: printk("ISILoad:Card%d reset failure (Possible bad I/O Port Address 0x%x).\n",card+1,base);
+#ifdef ISICOM_DEBUG			
+				 printk("Sig=0x%x\n",signature);
+#endif				 
+				 return -EIO;
+			}
+			printk("-Done\n");
+			return put_user(signature,(unsigned int*)arg);
+						
+	case	MIOCTL_LOAD_FIRMWARE:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+				
+			if(copy_from_user(&frame, (void *) arg, sizeof(bin_frame)))
+				return -EFAULT;
+			
+			if (WaitTillCardIsFree(base))
+				return -EIO;
+			
+			outw(0xf0,base);	/* start upload sequence */ 
+			outw(0x00,base);
+			outw((frame.addr), base);/*      lsb of adderess    */
+			
+			word_count=(frame.count >> 1) + frame.count % 2;
+			outw(word_count, base);
+			InterruptTheCard(base);
+			
+			for(i=0;i<=0x2f;i++);	/* a wee bit of delay */
+			
+			if (WaitTillCardIsFree(base)) 
+				return -EIO;
+				
+			if ((status=inw(base+0x4))!=0) {
+				printk(KERN_WARNING "ISILoad:Card%d rejected load header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
+				card+1, frame.addr, frame.count, status);
+				return -EIO;
+			}
+			outsw(base, (void *) frame.bin_data, word_count);
+			
+			InterruptTheCard(base);
+			
+			for(i=0;i<=0x0f;i++);	/* another wee bit of delay */ 
+			
+			if (WaitTillCardIsFree(base)) 
+				return -EIO;
+				
+			if ((status=inw(base+0x4))!=0) {
+				printk(KERN_ERR "ISILoad:Card%d got out of sync.Card Status:0x%x\n",card+1, status);
+				return -EIO;
+			}	
+			return 0;
+						
+	case	MIOCTL_READ_FIRMWARE:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+				
+			if(copy_from_user(&frame, (void *) arg, sizeof(bin_header)))
+				return -EFAULT;
+			
+			if (WaitTillCardIsFree(base))
+				return -EIO;
+			
+			outw(0xf1,base);	/* start download sequence */ 
+			outw(0x00,base);
+			outw((frame.addr), base);/*      lsb of adderess    */
+			
+			word_count=(frame.count >> 1) + frame.count % 2;
+			outw(word_count+1, base);
+			InterruptTheCard(base);
+			
+			for(i=0;i<=0xf;i++);	/* a wee bit of delay */
+			
+			if (WaitTillCardIsFree(base)) 
+				return -EIO;
+				
+			if ((status=inw(base+0x4))!=0) {
+				printk(KERN_WARNING "ISILoad:Card%d rejected verify header:\nAddress:0x%x \nCount:0x%x \nStatus:0x%x \n", 
+				card+1, frame.addr, frame.count, status);
+				return -EIO;
+			}
+			
+			inw(base);
+			insw(base, frame.bin_data, word_count);
+			InterruptTheCard(base);
+			
+			for(i=0;i<=0x0f;i++);	/* another wee bit of delay */ 
+			
+			if (WaitTillCardIsFree(base)) 
+				return -EIO;
+				
+			if ((status=inw(base+0x4))!=0) {
+				printk(KERN_ERR "ISILoad:Card%d verify got out of sync.Card Status:0x%x\n",card+1, status);
+				return -EIO;
+			}	
+			
+			if(copy_to_user((void *) arg, &frame, sizeof(bin_frame)))
+				return -EFAULT;
+			return 0;
+	
+	case	MIOCTL_XFER_CTRL:
+			if (!capable(CAP_SYS_ADMIN))
+				return -EPERM;
+			if (WaitTillCardIsFree(base)) 
+				return -EIO;
+					
+			outw(0xf2, base);
+			outw(0x800, base);
+			outw(0x0, base);
+			outw(0x0, base);
+			InterruptTheCard(base);
+			
+			isi_card[card].status |= FIRMWARE_LOADED;
+			return 0;	
+			
+	default:
+#ifdef ISICOM_DEBUG	
+		printk(KERN_DEBUG "ISILoad: Received Ioctl cmd 0x%x.\n", cmd); 
+#endif
+		return -ENOIOCTLCMD;
+	
+	}
+	
+}
+		        	
+
+/*
+ *	ISICOM Driver specific routines ...
+ *
+ */
+ 
+static inline int isicom_paranoia_check(struct isi_port const * port, kdev_t dev, 
+					const char * routine)
+{
+#ifdef ISICOM_DEBUG 
+	static const char * badmagic = 
+			KERN_WARNING "ISICOM: Warning: bad isicom magic for dev %s in %s.\n";
+	static const char * badport = 
+			KERN_WARNING "ISICOM: Warning: NULL isicom port for dev %s in %s.\n";		
+	if (!port) {
+		printk(badport, kdevname(dev), routine);
+		return 1;
+	}
+	if (port->magic != ISICOM_MAGIC) {
+		printk(badmagic, kdevname(dev), routine);
+		return 1;
+	}	
+#endif	
+	return 0;
+}
+			
+extern inline void schedule_bh(struct isi_port * port)
+{
+	queue_task(&port->bh_tqueue, &tq_isicom);
+	mark_bh(ISICOM_BH);
+} 
+
+/*	Transmitter	*/
+
+static void isicom_tx(unsigned long _data)
+{
+	short count = (BOARD_COUNT-1), card, base;
+	short txcount, wait, wrd, residue, word_count, cnt;
+	struct isi_port * port;
+	struct tty_struct * tty;
+	unsigned long flags;
+	
+#ifdef ISICOM_DEBUG
+	++tx_count;
+#endif	
+	
+	/*	find next active board	*/
+	card = (prev_card + 1) & 0x0003;
+	while(count-- > 0) {
+		if (isi_card[card].status & BOARD_ACTIVE) 
+			break;
+		card = (card + 1) & 0x0003;	
+	}
+	if (!(isi_card[card].status & BOARD_ACTIVE))
+		goto sched_again;
+		
+	prev_card = card;
+	
+	count = isi_card[card].port_count;
+	port = isi_card[card].ports;
+	base = isi_card[card].base;
+	for (;count > 0;count--, port++) {
+		/* port not active or tx disabled to force flow control */
+		if (!(port->status & ISI_TXOK))
+			continue;
+		
+		tty = port->tty;
+		save_flags(flags); cli();
+		txcount = MIN(TX_SIZE, port->xmit_cnt);
+		if ((txcount <= 0) || tty->stopped || tty->hw_stopped) {
+			restore_flags(flags);
+			continue;
+		}
+		wait = 200;	
+		while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+		if (wait <= 0) {
+			restore_flags(flags);
+#ifdef ISICOM_DEBUG
+			printk(KERN_DEBUG "ISICOM: isicom_tx:Card(0x%x) found busy.\n",
+				card);
+#endif
+			continue;
+		}
+		if (!(inw(base + 0x02) & (1 << port->channel))) {
+			restore_flags(flags);
+#ifdef ISICOM_DEBUG					
+			printk(KERN_DEBUG "ISICOM: isicom_tx: cannot tx to 0x%x:%d.\n",
+					base, port->channel + 1);
+#endif					
+			continue;		
+		}
+#ifdef ISICOM_DEBUG
+		printk(KERN_DEBUG "ISICOM: txing %d bytes, port%d.\n", 
+				txcount, port->channel+1); 
+#endif	
+		outw((port->channel << isi_card[card].shift_count) | txcount
+					, base);
+		residue = NO;
+		wrd = 0;			
+		while (1) {
+			cnt = MIN(txcount, (SERIAL_XMIT_SIZE - port->xmit_tail));
+			if (residue == YES) {
+				residue = NO;
+				if (cnt > 0) {
+					wrd |= (port->xmit_buf[port->xmit_tail] << 8);
+					port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+					port->xmit_cnt--;
+					txcount--;
+					cnt--;
+					outw(wrd, base);			
+				}
+				else {
+					outw(wrd, base);
+					break;
+				}
+			}		
+			if (cnt <= 0) break;
+			word_count = cnt >> 1;
+			outsw(base, port->xmit_buf+port->xmit_tail, word_count);
+			port->xmit_tail = (port->xmit_tail + (word_count << 1)) &
+						(SERIAL_XMIT_SIZE - 1);
+			txcount -= (word_count << 1);
+			port->xmit_cnt -= (word_count << 1);
+			if (cnt & 0x0001) {
+				residue = YES;
+				wrd = port->xmit_buf[port->xmit_tail];
+				port->xmit_tail = (port->xmit_tail + 1) & (SERIAL_XMIT_SIZE - 1);
+				port->xmit_cnt--;
+				txcount--;
+			}
+		}
+/*
+ *	Replaced the code below with hopefully a faster loop - sameer
+ */
+
+/*					
+		while (1) {
+			wrd = port->xmit_buf[port->xmit_tail++];
+			port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+			port->xmit_cnt--;
+			if (--txcount > 0) {
+				wrd |= (port->xmit_buf[port->xmit_tail++] << 8);
+				port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
+				port->xmit_cnt--;
+				outw(wrd, base);
+				if (--txcount <= 0) break;
+			}
+			else {
+				outw(wrd, base);
+				break;
+			}
+		}
+*/
+		InterruptTheCard(base);
+		if (port->xmit_cnt <= 0)
+			port->status &= ~ISI_TXOK;
+		if (port->xmit_cnt <= WAKEUP_CHARS)
+			schedule_bh(port);
+		restore_flags(flags);
+	}	
+
+		/*	schedule another tx for hopefully in about 10ms	*/	
+sched_again:	
+	if (!re_schedule)	
+		return;
+	init_timer(&tx);
+	tx.expires = jiffies + HZ/100;
+	tx.data = 0;
+	tx.function = isicom_tx;
+	add_timer(&tx);
+	
+	return;	
+}		
+ 
+/* 	Interrupt handlers 	*/
+
+static void do_isicom_bh(void)
+{
+	run_task_queue(&tq_isicom);
+}
+
+
+ 
+static void isicom_bottomhalf(void * data)
+{
+	struct isi_port * port = (struct isi_port *) data;
+	struct tty_struct * tty = port->tty;
+	
+	if (!tty)
+		return;
+	
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+	wake_up_interruptible(&tty->write_wait);
+} 		
+ 		
+/* main interrupt handler routine */ 		
+static void isicom_interrupt(int irq, void * dev_id, struct pt_regs * regs)
+{
+	struct isi_board * card;
+	struct isi_port * port;
+	struct tty_struct * tty;
+	unsigned short base, header, word_count, count;
+	unsigned char channel;
+	short byte_count;
+	
+	card = irq_to_board[irq];
+	if (!card || !(card->status & FIRMWARE_LOADED)) {
+		printk(KERN_DEBUG "ISICOM: interrupt: not handling irq%d!.\n", irq);
+		return;
+	}
+	base = card->base;
+	
+	inw(base);		/* get the dummy word out */
+	header = inw(base);
+	channel = (header & 0x7800) >> card->shift_count;
+	byte_count = header & 0xff;
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM:Intr:(0x%x:%d).\n", base, channel+1);
+#endif	
+	if ((channel+1) > card->port_count) {
+		printk(KERN_WARNING "ISICOM: isicom_interrupt(0x%x): %d(channel) > port_count.\n",
+				base, channel+1);
+		ClearInterrupt(base);		
+		return;			
+	}
+	port = card->ports + channel;
+	if (!(port->flags & ASYNC_INITIALIZED)) {
+		ClearInterrupt(base);
+		return;
+	}	
+		
+	tty = port->tty;
+	
+	if (header & 0x8000) {		/* Status Packet */
+		header = inw(base);
+		switch(header & 0xff) {
+			case 0:	/* Change in EIA signals */
+				
+				if (port->flags & ASYNC_CHECK_CD) {
+					if (port->status & ISI_DCD) {
+						if (!(header & ISI_DCD)) {
+						/* Carrier has been lost  */
+#ifdef ISICOM_DEBUG						
+							printk(KERN_DEBUG "ISICOM: interrupt: DCD->low.\n");
+#endif							
+							port->status &= ~ISI_DCD;
+							if (!((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+								(port->flags & ASYNC_CALLOUT_NOHUP)))
+								queue_task(&port->hangup_tq,
+									&tq_scheduler);
+						}
+					}
+					else {
+						if (header & ISI_DCD) {
+						/* Carrier has been detected */
+#ifdef ISICOM_DEBUG
+							printk(KERN_DEBUG "ISICOM: interrupt: DCD->high.\n");
+#endif							
+							port->status |= ISI_DCD;
+							wake_up_interruptible(&port->open_wait);
+						}
+					}
+				}
+				else {
+					if (header & ISI_DCD) 
+						port->status |= ISI_DCD;
+					else
+						port->status &= ~ISI_DCD;
+				}	
+				
+				if (port->flags & ASYNC_CTS_FLOW) {
+					if (port->tty->hw_stopped) {
+						if (header & ISI_CTS) {
+							port->tty->hw_stopped = 0;
+							/* start tx ing */
+							port->status |= (ISI_TXOK | ISI_CTS);
+							schedule_bh(port);
+						}
+					}
+					else {
+						if (!(header & ISI_CTS)) {
+							port->tty->hw_stopped = 1;
+							/* stop tx ing */
+							port->status &= ~(ISI_TXOK | ISI_CTS);
+						}
+					}
+				}
+				else {
+					if (header & ISI_CTS) 
+						port->status |= ISI_CTS;
+					else
+						port->status &= ~ISI_CTS;
+				}
+				
+				if (header & ISI_DSR) 
+					port->status |= ISI_DSR;
+				else
+					port->status &= ~ISI_DSR;
+				
+				if (header & ISI_RI) 
+					port->status |= ISI_RI;
+				else
+					port->status &= ~ISI_RI;						
+				
+				break;
+				
+			case 1:	/* Received Break !!!	 */
+				if (tty->flip.count >= TTY_FLIPBUF_SIZE)
+					break;
+				*tty->flip.flag_buf_ptr++ = TTY_BREAK;
+				/* dunno if this is right */	
+				*tty->flip.char_buf_ptr++ = 0;
+				tty->flip.count++;
+				if (port->flags & ASYNC_SAK)
+					do_SAK(tty);
+				queue_task(&tty->flip.tqueue, &tq_timer);
+				break;
+				
+			case 2:	/* Statistics		 */
+				printk(KERN_DEBUG "ISICOM: isicom_interrupt: stats!!!.\n");			
+				break;
+				
+			default:
+				printk(KERN_WARNING "ISICOM: Intr: Unknown code in status packet.\n");
+				break;
+		}	 
+	}
+	else {				/* Data   Packet */
+		count = MIN(byte_count, (TTY_FLIPBUF_SIZE - tty->flip.count));
+#ifdef ISICOM_DEBUG
+		printk(KERN_DEBUG "ISICOM: Intr: Can rx %d of %d bytes.\n", 
+					count, byte_count);
+#endif			
+		word_count = count >> 1;
+		insw(base, tty->flip.char_buf_ptr, word_count);
+		tty->flip.char_buf_ptr += (word_count << 1);		
+		byte_count -= (word_count << 1);
+		if (count & 0x0001) {
+			*tty->flip.char_buf_ptr++ = (char)(inw(base) & 0xff);
+			byte_count -= 2;
+		}	
+		memset(tty->flip.flag_buf_ptr, 0, count);
+		tty->flip.flag_buf_ptr += count;
+		tty->flip.count += count;
+		
+		if (byte_count > 0) {
+			printk(KERN_DEBUG "ISICOM: Intr(0x%x:%d): Flip buffer overflow! dropping bytes...\n",
+					base, channel+1);
+			while(byte_count > 0) { /* drain out unread xtra data */
+				inw(base);
+				byte_count -= 2;
+			}
+		}
+		queue_task(&tty->flip.tqueue, &tq_timer);
+	}
+	ClearInterrupt(base);
+	return;
+} 
+
+ /* called with interrupts disabled */ 
+static void isicom_config_port(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	struct tty_struct * tty;
+	unsigned long baud;
+	unsigned short channel_setup, wait, base = card->base;
+	unsigned short channel = port->channel, shift_count = card->shift_count;
+	unsigned char flow_ctrl;
+	
+	if (!(tty = port->tty) || !tty->termios)
+		return;
+	baud = C_BAUD(tty);
+	if (baud & CBAUDEX) {
+		baud &= ~CBAUDEX;
+		
+		/*  if CBAUDEX bit is on and the baud is set to either 50 or 75
+		 *  then the card is programmed for 57.6Kbps or 115Kbps
+		 *  respectively.
+		 */   
+		 
+		if (baud < 1 || baud > 2)
+			port->tty->termios->c_cflag &= ~CBAUDEX;
+		else
+			baud += 15;
+	}	
+	if (baud == 15) {
+	
+		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set 
+		 *  by the set_serial_info ioctl ... this is done by
+		 *  the 'setserial' utility.
+		 */  
+			
+		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
+			baud++;     /*  57.6 Kbps */
+		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
+			baud +=2;   /*  115  Kbps */	 
+	}
+	if (linuxb_to_isib[baud] == -1) {
+		/* hang up */
+	 	drop_dtr(port);
+	 	return;
+	}	
+	else  
+		raise_dtr(port);
+		
+	wait = 100;	
+	while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));	
+	if (!wait) {
+		printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at channel setup.\n");
+		return;
+	}			 
+	outw(0x8000 | (channel << shift_count) |0x03, base);
+	outw(linuxb_to_isib[baud] << 8 | 0x03, base);
+	channel_setup = 0;
+	switch(C_CSIZE(tty)) {
+		case CS5:
+			channel_setup |= ISICOM_CS5;
+			break;
+		case CS6:
+			channel_setup |= ISICOM_CS6;
+			break;
+		case CS7:
+			channel_setup |= ISICOM_CS7;
+			break;
+		case CS8:
+			channel_setup |= ISICOM_CS8;
+			break;
+	}
+		
+	if (C_CSTOPB(tty))
+		channel_setup |= ISICOM_2SB;
+	
+	if (C_PARENB(tty))
+		channel_setup |= ISICOM_EVPAR;
+	if (C_PARODD(tty))
+		channel_setup |= ISICOM_ODPAR;	
+	outw(channel_setup, base);	
+	InterruptTheCard(base);
+	
+	if (C_CLOCAL(tty))
+		port->flags &= ~ASYNC_CHECK_CD;
+	else
+		port->flags |= ASYNC_CHECK_CD;	
+	
+	/* flow control settings ...*/
+	flow_ctrl = 0;
+	port->flags &= ~ASYNC_CTS_FLOW;
+	if (C_CRTSCTS(tty)) {
+		port->flags |= ASYNC_CTS_FLOW;
+		flow_ctrl |= ISICOM_CTSRTS;
+	}	
+	if (I_IXON(tty))	
+		flow_ctrl |= ISICOM_RESPOND_XONXOFF;
+	if (I_IXOFF(tty))
+		flow_ctrl |= ISICOM_INITIATE_XONXOFF;	
+		
+	wait = 100;	
+	while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));	
+	if (!wait) {
+		printk(KERN_WARNING "ISICOM: Card found busy in isicom_config_port at flow setup.\n");
+		return;
+	}			 
+	outw(0x8000 | (channel << shift_count) |0x04, base);
+	outw(flow_ctrl << 8 | 0x05, base);
+	outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
+	InterruptTheCard(base);
+	
+	/*	rx enabled -> enable port for rx on the card	*/
+	if (C_CREAD(tty)) {
+		card->port_status |= (1 << channel);
+		outw(card->port_status, base + 0x02);
+	}
+		
+}
+ 
+/* open et all */ 
+
+extern inline void isicom_setup_board(struct isi_board * bp)
+{
+	int channel;
+	struct isi_port * port;
+	unsigned long flags;
+	
+	if (bp->status & BOARD_ACTIVE) 
+		return;
+	port = bp->ports;
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts start, port_count %d...\n", bp->port_count);
+#endif
+	for(channel = 0; channel < bp->port_count; channel++, port++) {
+		save_flags(flags); cli();
+		drop_dtr_rts(port);
+		restore_flags(flags);
+	}
+#ifdef ISICOM_DEBUG		
+	printk(KERN_DEBUG "ISICOM: setup_board: drop_dtr_rts stop...\n");	
+#endif	
+	
+	bp->status |= BOARD_ACTIVE;
+	MOD_INC_USE_COUNT;
+	return;
+}
+ 
+static int isicom_setup_port(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	unsigned long flags;
+	
+	if (port->flags & ASYNC_INITIALIZED)
+		return 0;
+	if (!port->xmit_buf) {
+		unsigned long page;
+		
+		if (!(page = get_free_page(GFP_KERNEL)))
+			return -ENOMEM;
+		
+		if (port->xmit_buf) {
+			free_page(page);
+			return -ERESTARTSYS;
+		}
+		port->xmit_buf = (unsigned char *) page;	
+	}	
+	save_flags(flags); cli();
+	if (port->tty)
+		clear_bit(TTY_IO_ERROR, &port->tty->flags);
+	if (port->count == 1)
+		card->count++;
+		
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	
+	/*	discard any residual data	*/
+	kill_queue(port, ISICOM_KILLTX | ISICOM_KILLRX);
+	
+	isicom_config_port(port);
+	port->flags |= ASYNC_INITIALIZED;
+	
+	restore_flags(flags);
+	
+	return 0;		
+} 
+ 
+static int block_til_ready(struct tty_struct * tty, struct file * filp, struct isi_port * port) 
+{
+	int do_clocal = 0, retval;
+	struct wait_queue wait = { current, NULL };
+
+	/* block if port is in the process of being closed */
+
+	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
+#ifdef ISICOM_DEBUG	
+		printk(KERN_DEBUG "ISICOM: block_til_ready: close in progress.\n");
+#endif		
+		interruptible_sleep_on(&port->close_wait);
+		if (port->flags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+	}
+	
+	/* trying to open a callout device... check for constraints */
+	
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+#ifdef ISICOM_DEBUG
+		printk(KERN_DEBUG "ISICOM: bl_ti_rdy: callout open.\n");	
+#endif		
+		if (port->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (port->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (port->session != current->session))
+			return -EBUSY;
+			
+		if ((port->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (port->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (port->pgrp != current->pgrp))
+			return -EBUSY;
+		port->flags |= ASYNC_CALLOUT_ACTIVE;
+		cli();
+		raise_dtr_rts(port);
+		sti();
+		return 0;
+	}
+	
+	/* if non-blocking mode is set ... */
+	
+	if ((filp->f_flags & O_NONBLOCK) || (tty->flags & (1 << TTY_IO_ERROR))) {
+#ifdef ISICOM_DEBUG	
+		printk(KERN_DEBUG "ISICOM: block_til_ready: non-block mode.\n");
+#endif		
+		if (port->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		port->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;	
+	}	
+	
+	if (port->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (port->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1; 
+	} else {
+		if (C_CLOCAL(tty))
+			do_clocal = 1;
+	}
+#ifdef ISICOM_DEBUG	
+	if (do_clocal)
+		printk(KERN_DEBUG "ISICOM: block_til_ready: CLOCAL set.\n");
+#endif 		
+	
+	/* block waiting for DCD to be asserted, and while 
+						callout dev is busy */
+	retval = 0;
+	add_wait_queue(&port->open_wait, &wait);
+	cli();
+		if (!tty_hung_up_p(filp))
+			port->count--;
+	sti();
+	port->blocked_open++;
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: block_til_ready: waiting for DCD...\n");
+#endif	
+	while (1) {
+		cli();
+		if (!(port->flags & ASYNC_CALLOUT_ACTIVE)) 
+			raise_dtr_rts(port);
+		
+		sti();
+		current->state = TASK_INTERRUPTIBLE;
+		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { 	
+			if (port->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;
+#ifdef ISICOM_DEBUG				
+			printk(KERN_DEBUG "ISICOM: block_til_ready: tty_hung_up_p || not init.\n"); 
+#endif			
+			break;
+		}	
+		if (!(port->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(port->flags & ASYNC_CLOSING) &&
+		    (do_clocal || (port->status & ISI_DCD))) {
+#ifdef ISICOM_DEBUG		    
+		 	printk(KERN_DEBUG "ISICOM: block_til_ready: do_clocal || DCD.\n");   
+#endif		 	
+			break;
+		}	
+		if (signal_pending(current)) {
+#ifdef ISICOM_DEBUG		
+			printk(KERN_DEBUG "ISICOM: block_til_ready: sig blocked.\n");
+#endif			
+			retval = -ERESTARTSYS;
+			break;
+		}
+		schedule();		
+	}
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&port->open_wait, &wait);
+	if (!tty_hung_up_p(filp))
+		port->count++;
+	port->blocked_open--;
+	if (retval)
+		return retval;
+	port->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}
+ 
+static int isicom_open(struct tty_struct * tty, struct file * filp)
+{
+	struct isi_port * port;
+	struct isi_board * card;
+	unsigned int line, board;
+	unsigned long flags;
+	int error;
+
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: open start!!!.\n");
+#endif	
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "line = %d.\n", line);
+#endif	
+	
+	if ((line < 0) || (line > (PORT_COUNT-1)))
+		return -ENODEV;
+	board = BOARD(line);
+	
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "board = %d.\n", board);
+#endif	
+	
+	card = &isi_card[board];
+	if (!(card->status & FIRMWARE_LOADED)) {
+#ifdef ISICOM_DEBUG	
+		printk(KERN_DEBUG"ISICOM: Firmware not loaded to card%d.\n", board);
+#endif		
+		return -ENODEV;
+	}
+	
+	/*  open on higher 8 dev files on a 8 port card !!! */
+	if (card->port_count == 8) 
+		if (line > ((board * 16)+7)) {
+			printk(KERN_ERR "ISICOM: Opened >8 on a 8 port card.\n");
+			return -ENODEV;
+		}	
+	port = &isi_ports[line];	
+	if (isicom_paranoia_check(port, tty->device, "isicom_open"))
+		return -ENODEV;
+		
+#ifdef ISICOM_DEBUG		
+	printk(KERN_DEBUG "ISICOM: isicom_setup_board ...\n");		
+#endif	
+	isicom_setup_board(card);		
+	
+	port->count++;
+	tty->driver_data = port;
+	port->tty = tty;
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: isicom_setup_port ...\n");
+#endif	
+	if ((error = isicom_setup_port(port))!=0)
+		return error;
+#ifdef ISICOM_DEBUG		
+	printk(KERN_DEBUG "ISICOM: block_til_ready ...\n");	
+#endif	
+	if ((error = block_til_ready(tty, filp, port))!=0)
+		return error;
+		
+	if ((port->count == 1) && (port->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = port->normal_termios;
+		else 
+			*tty->termios = port->callout_termios;
+		save_flags(flags); cli();
+		isicom_config_port(port);
+		restore_flags(flags);		
+	}	
+	
+	port->session = current->session;	
+	port->pgrp = current->pgrp;
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: open end!!!.\n");
+#endif	
+	return 0;      		
+}
+ 
+/* close et all */
+
+extern inline void isicom_shutdown_board(struct isi_board * bp)
+{
+	int channel;
+	struct isi_port * port;
+	
+	if (!(bp->status & BOARD_ACTIVE))
+		return;
+	bp->status &= ~BOARD_ACTIVE;
+	port = bp->ports;
+	for(channel = 0; channel < bp->port_count; channel++, port++) {
+		drop_dtr_rts(port);
+	}	
+	MOD_DEC_USE_COUNT;
+}
+
+static void isicom_shutdown_port(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	struct tty_struct * tty;	
+	
+	if (!(port->flags & ASYNC_INITIALIZED))
+		return;
+	if (port->xmit_buf) {
+		free_page((unsigned long) port->xmit_buf);
+		port->xmit_buf = NULL;
+	}	
+	if (!(tty = port->tty) || C_HUPCL(tty)) 
+		/* drop dtr on this port */
+		drop_dtr(port);
+		
+	/* any other port uninits  */ 
+	
+	if (tty)
+		set_bit(TTY_IO_ERROR, &tty->flags);
+	port->flags &= ~ASYNC_INITIALIZED;
+	
+	if (--card->count < 0) {
+		printk(KERN_DEBUG "ISICOM: isicom_shutdown_port: bad board(0x%x) count %d.\n",
+			card->base, card->count);
+		card->count = 0;	
+	}
+	
+	/* last port was closed , shutdown that boad too */
+	if (!card->count)
+		isicom_shutdown_board(card);
+}
+
+static void isicom_close(struct tty_struct * tty, struct file * filp)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_board * card = port->card;
+	unsigned long flags;
+	
+	if (!port)
+		return;
+	if (isicom_paranoia_check(port, tty->device, "isicom_close"))
+		return;
+	
+#ifdef ISICOM_DEBUG		
+	printk(KERN_DEBUG "ISICOM: Close start!!!.\n");
+#endif	
+	
+	save_flags(flags); cli();
+	if (tty_hung_up_p(filp)) {
+		restore_flags(flags);
+		return;
+	}
+	
+	if ((tty->count == 1) && (port->count != 1)) {
+		printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count"
+			"tty->count = 1	port count = %d.\n",
+			card->base, port->count);
+		port->count = 1;
+	}
+	if (--port->count < 0) {
+		printk(KERN_WARNING "ISICOM:(0x%x) isicom_close: bad port count for"
+			"channel%d = %d", card->base, port->channel, 
+			port->count);
+		port->count = 0;	
+	}
+	
+	if (port->count) {
+		restore_flags(flags);
+		return;
+	} 	
+	port->flags |= ASYNC_CLOSING;
+	/* 
+	 * save termios struct since callout and dialin termios may be 
+	 * different.
+	 */	
+	if (port->flags & ASYNC_NORMAL_ACTIVE)
+		port->normal_termios = *tty->termios;
+	if (port->flags & ASYNC_CALLOUT_ACTIVE)
+		port->callout_termios = *tty->termios;
+	
+	tty->closing = 1;
+	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, port->closing_wait);
+	/* indicate to the card that no more data can be received 
+	   on this port */
+	if (port->flags & ASYNC_INITIALIZED) {   
+		card->port_status &= ~(1 << port->channel);
+		outw(card->port_status, card->base + 0x02);
+	}	
+	isicom_shutdown_port(port);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	port->tty = 0;
+	if (port->blocked_open) {
+		if (port->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+#ifdef ISICOM_DEBUG			
+			printk(KERN_DEBUG "ISICOM: scheduling until time out.\n");
+#endif			
+			schedule_timeout(port->close_delay);
+		}
+		wake_up_interruptible(&port->open_wait);
+	}	
+	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE | 
+			ASYNC_CLOSING);
+	wake_up_interruptible(&port->close_wait);
+	restore_flags(flags);
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: Close end!!!.\n");
+#endif	
+}
+
+/* write et all */
+static int isicom_write(struct tty_struct * tty, int from_user,
+			const unsigned char * buf, int count)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	unsigned long flags;
+	int cnt, total = 0;
+#ifdef ISICOM_DEBUG
+	printk(KERN_DEBUG "ISICOM: isicom_write for port%d: %d bytes.\n",
+			port->channel+1, count);
+#endif	  	
+	if (isicom_paranoia_check(port, tty->device, "isicom_write"))
+		return 0;
+	
+	if (!tty || !port->xmit_buf || !tmp_buf)
+		return 0;
+	if (from_user)
+		down(&tmp_buf_sem); /* acquire xclusive access to tmp_buf */
+		
+	save_flags(flags);
+	while(1) {	
+		cli();
+		cnt = MIN(count, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			SERIAL_XMIT_SIZE - port->xmit_head));
+		if (cnt <= 0) 
+			break;
+		
+		if (from_user) {
+			/* the following may block for paging... hence 
+			   enabling interrupts but tx routine may have 
+			   created more space in xmit_buf when the ctrl 
+			   gets back here  */
+			sti(); 
+			copy_from_user(tmp_buf, buf, cnt);
+			cli();
+			cnt = MIN(cnt, MIN(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
+			SERIAL_XMIT_SIZE - port->xmit_head));
+			memcpy(port->xmit_buf + port->xmit_head, tmp_buf, cnt);
+		}	
+		else
+			memcpy(port->xmit_buf + port->xmit_head, buf, cnt);
+		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE - 1);
+		port->xmit_cnt += cnt;
+		restore_flags(flags);
+		buf += cnt;
+		count -= cnt;
+		total += cnt;
+	}		
+	if (from_user)
+		up(&tmp_buf_sem);
+	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
+		port->status |= ISI_TXOK;
+	restore_flags(flags);
+#ifdef ISICOM_DEBUG
+	printk(KERN_DEBUG "ISICOM: isicom_write %d bytes written.\n", total);
+#endif		
+	return total;	
+}
+
+/* put_char et all */
+static void isicom_put_char(struct tty_struct * tty, unsigned char ch)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	unsigned long flags;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_put_char"))
+		return;
+	
+	if (!tty || !port->xmit_buf)
+		return;
+#ifdef ISICOM_DEBUG
+	printk(KERN_DEBUG "ISICOM: put_char, port %d, char %c.\n", port->channel+1, ch);
+#endif			
+		
+	save_flags(flags); cli();
+	
+	if (port->xmit_cnt >= (SERIAL_XMIT_SIZE - 1)) {
+		restore_flags(flags);
+		return;
+	}
+	
+	port->xmit_buf[port->xmit_head++] = ch;
+	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
+	port->xmit_cnt++;
+	restore_flags(flags);
+}
+
+/* flush_chars et all */
+static void isicom_flush_chars(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_flush_chars"))
+		return;
+	
+	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
+	    !port->xmit_buf)
+		return;
+		
+	/* this tells the transmitter to consider this port for
+	   data output to the card ... that's the best we can do. */
+	port->status |= ISI_TXOK;	
+}
+
+/* write_room et all */
+static int isicom_write_room(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	int free;
+	if (isicom_paranoia_check(port, tty->device, "isicom_write_room"))
+		return 0;
+	
+	free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
+	if (free < 0)
+		free = 0;
+	return free;
+}
+
+/* chars_in_buffer et all */
+static int isicom_chars_in_buffer(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	if (isicom_paranoia_check(port, tty->device, "isicom_chars_in_buffer"))
+		return 0;
+	return port->xmit_cnt;
+}
+
+/* ioctl et all */
+extern inline void isicom_send_break(struct isi_port * port, unsigned long length)
+{
+	struct isi_board * card = port->card;
+	short wait = 10;
+	unsigned short base = card->base;	
+	unsigned long flags;
+	
+	save_flags(flags); cli();
+	while (((inw(base + 0x0e) & 0x0001) == 0) && (wait-- > 0));	
+	if (!wait) {
+		printk(KERN_DEBUG "ISICOM: Card found busy in isicom_send_break.\n");
+		return;
+	}	
+	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
+	outw((length & 0xff) << 8 | 0x00, base);
+	outw((length & 0xff00), base);
+	InterruptTheCard(base);
+	restore_flags(flags);
+}
+
+static int isicom_get_modem_info(struct isi_port * port, unsigned int * value)
+{
+	/* just send the port status */
+	unsigned int info;
+	unsigned short status = port->status;
+	
+	info =  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
+		((status & ISI_DTR) ? TIOCM_DTR : 0) |
+		((status & ISI_DCD) ? TIOCM_CAR : 0) |
+		((status & ISI_DSR) ? TIOCM_DSR : 0) |
+		((status & ISI_CTS) ? TIOCM_CTS : 0) |
+		((status & ISI_RI ) ? TIOCM_RI  : 0);
+	put_user(info, (unsigned long *) value);
+	return 0;	
+}
+
+static int isicom_set_modem_info(struct isi_port * port, unsigned int cmd,
+					unsigned int * value)
+{
+	unsigned int arg;
+	unsigned long flags;
+	
+	if(get_user(arg, value))
+		return -EFAULT;
+	
+	save_flags(flags); cli();
+	
+	switch(cmd) {
+		case TIOCMBIS:
+			if (arg & TIOCM_RTS) 
+				raise_rts(port);
+			if (arg & TIOCM_DTR) 
+				raise_dtr(port);
+			break;
+		
+		case TIOCMBIC:
+			if (arg & TIOCM_RTS)
+				drop_rts(port);
+			if (arg & TIOCM_DTR)
+				drop_dtr(port);	
+			break;
+			
+		case TIOCMSET:
+			if (arg & TIOCM_RTS)
+				raise_rts(port);
+			else
+				drop_rts(port);
+			
+			if (arg & TIOCM_DTR)
+				raise_dtr(port);
+			else
+				drop_dtr(port);
+			break;
+		
+		default:
+			restore_flags(flags);
+			return -EINVAL;		 	
+	}
+	restore_flags(flags);
+	return 0;
+}			
+
+static int isicom_set_serial_info(struct isi_port * port,
+					struct serial_struct * info)
+{
+	struct serial_struct newinfo;
+	unsigned long flags;
+	int reconfig_port;
+
+	if(copy_from_user(&newinfo, info, sizeof(newinfo)))
+		return -EFAULT;
+		
+	reconfig_port = ((port->flags & ASYNC_SPD_MASK) != 
+			 (newinfo.flags & ASYNC_SPD_MASK));
+	
+	if (!suser()) {
+		if ((newinfo.close_delay != port->close_delay) ||
+		    (newinfo.closing_wait != port->closing_wait) ||
+		    ((newinfo.flags & ~ASYNC_USR_MASK) != 
+		     (port->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		port->flags = ((port->flags & ~ ASYNC_USR_MASK) |
+				(newinfo.flags & ASYNC_USR_MASK));
+	}	
+	else {
+		port->close_delay = newinfo.close_delay;
+		port->closing_wait = newinfo.closing_wait; 
+		port->flags = ((port->flags & ~ASYNC_FLAGS) | 
+				(newinfo.flags & ASYNC_FLAGS));
+	}
+	if (reconfig_port) {
+		save_flags(flags); cli();
+		isicom_config_port(port);
+		restore_flags(flags);
+	}
+	return 0;		 
+}		
+
+static int isicom_get_serial_info(struct isi_port * port, 
+					struct serial_struct * info)
+{
+	struct serial_struct out_info;
+	
+	memset(&out_info, 0, sizeof(out_info));
+/*	out_info.type = ? */
+	out_info.line = port - isi_ports;
+	out_info.port = port->card->base;
+	out_info.irq = port->card->irq;
+	out_info.flags = port->flags;
+/*	out_info.baud_base = ? */
+	out_info.close_delay = port->close_delay;
+	out_info.closing_wait = port->closing_wait;
+	if(copy_to_user(info, &out_info, sizeof(out_info)))
+		return -EFAULT;
+	return 0;
+}					
+
+static int isicom_ioctl(struct tty_struct * tty, struct file * filp,
+			unsigned int cmd, unsigned long arg) 
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	int retval;
+
+	if (isicom_paranoia_check(port, tty->device, "isicom_ioctl"))
+		return -ENODEV;
+
+	switch(cmd) {
+		case TCSBRK:
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (!arg)
+				isicom_send_break(port, HZ/4);
+			return 0;
+			
+		case TCSBRKP:	
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			isicom_send_break(port, arg ? arg * (HZ/10) : HZ/4);
+			return 0;
+			
+		case TIOCGSOFTCAR:
+			return put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+			
+		case TIOCSSOFTCAR:
+			if(get_user(arg, (unsigned long *) arg))
+				return -EFAULT;
+			tty->termios->c_cflag =
+				((tty->termios->c_cflag & ~CLOCAL) |
+				(arg ? CLOCAL : 0));
+			return 0;	
+			
+		case TIOCMGET:
+			return isicom_get_modem_info(port, (unsigned int*) arg);
+			
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET: 	
+			return isicom_set_modem_info(port, cmd, 
+					(unsigned int *) arg);
+		
+		case TIOCGSERIAL:
+			return isicom_get_serial_info(port, 
+					(struct serial_struct *) arg);
+		
+		case TIOCSSERIAL:
+			return isicom_set_serial_info(port,
+					(struct serial_struct *) arg);
+					
+		default:
+			return -ENOIOCTLCMD;						
+	}
+	return 0;
+}
+
+/* set_termios et all */
+static void isicom_set_termios(struct tty_struct * tty, struct termios * old_termios)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	unsigned long flags;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_set_termios"))
+		return;
+	
+	if (tty->termios->c_cflag == old_termios->c_cflag &&
+	    tty->termios->c_iflag == old_termios->c_iflag)
+		return;
+		
+	save_flags(flags); cli();
+	isicom_config_port(port);
+	restore_flags(flags);
+	
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {	
+		tty->hw_stopped = 0;
+		isicom_start(tty);   
+	}    
+}
+
+/* throttle et all */
+static void isicom_throttle(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_board * card = port->card;
+	unsigned long flags;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_throttle"))
+		return;
+	
+	/* tell the card that this port cannot handle any more data for now */
+	save_flags(flags); cli();
+	card->port_status &= ~(1 << port->channel);
+	outw(card->port_status, card->base + 0x02);
+	restore_flags(flags);
+}
+
+/* unthrottle et all */
+static void isicom_unthrottle(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	struct isi_board * card = port->card;
+	unsigned long flags;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_unthrottle"))
+		return;
+	
+	/* tell the card that this port is ready to accept more data */
+	save_flags(flags); cli();
+	card->port_status |= (1 << port->channel);
+	outw(card->port_status, card->base + 0x02);
+	restore_flags(flags);
+}
+
+/* stop et all */
+static void isicom_stop(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+
+	if (isicom_paranoia_check(port, tty->device, "isicom_stop"))
+		return;
+	
+	/* this tells the transmitter not to consider this port for
+	   data output to the card. */
+	port->status &= ~ISI_TXOK;
+}
+
+/* start et all */
+static void isicom_start(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_start"))
+		return;
+	
+	/* this tells the transmitter to consider this port for
+	   data output to the card. */
+	port->status |= ISI_TXOK;
+}
+
+/* hangup et all */
+static void do_isicom_hangup(void * data)
+{
+	struct isi_port * port = (struct isi_port *) data;
+	struct tty_struct * tty;
+	
+	tty = port->tty;
+	if (!tty)
+		return;
+		
+	tty_hangup(tty);	
+}
+
+static void isicom_hangup(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_hangup"))
+		return;
+	
+	isicom_shutdown_port(port);
+	port->count = 0;
+	port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CALLOUT_ACTIVE);
+	port->tty = 0;
+	wake_up_interruptible(&port->open_wait);
+}
+
+/* flush_buffer et all */
+static void isicom_flush_buffer(struct tty_struct * tty)
+{
+	struct isi_port * port = (struct isi_port *) tty->driver_data;
+	unsigned long flags;
+	
+	if (isicom_paranoia_check(port, tty->device, "isicom_flush_buffer"))
+		return;
+	
+	save_flags(flags); cli();
+	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+	restore_flags(flags);
+	
+	wake_up_interruptible(&tty->write_wait);
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+
+static int register_ioregion(void)
+{
+	int count, done=0;
+	for (count=0; count < BOARD_COUNT; count++ ) {
+		if (isi_card[count].base) {
+			if (check_region(isi_card[count].base,16)) {
+				printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x is busy. Card%d will be disabled.\n",
+					isi_card[count].base,isi_card[count].base+15,count+1);
+				isi_card[count].base=0;
+			}
+			else {
+				request_region(isi_card[count].base,16,ISICOM_NAME);
+#ifdef ISICOM_DEBUG				
+				printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x requested for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+#endif				
+				done++;
+			}
+		}	
+	}
+	return done;
+}
+
+static void unregister_ioregion(void)
+{
+	int count;
+	for (count=0; count < BOARD_COUNT; count++ ) 
+		if (isi_card[count].base) {
+			release_region(isi_card[count].base,16);
+#ifdef ISICOM_DEBUG			
+			printk(KERN_DEBUG "ISICOM: I/O Region 0x%x-0x%x released for Card%d.\n",isi_card[count].base,isi_card[count].base+15,count+1);
+#endif			
+		}
+}
+
+static int register_drivers(void)
+{
+	int error;
+
+	/* tty driver structure initialization */
+	memset(&isicom_normal, 0, sizeof(struct tty_driver));
+	isicom_normal.magic	= TTY_DRIVER_MAGIC;
+	isicom_normal.name 	= "ttyM";
+	isicom_normal.major	= ISICOM_NMAJOR;
+	isicom_normal.minor_start	= 0;
+	isicom_normal.num	= PORT_COUNT;
+	isicom_normal.type	= TTY_DRIVER_TYPE_SERIAL;
+	isicom_normal.subtype	= SERIAL_TYPE_NORMAL;
+	isicom_normal.init_termios	= tty_std_termios;
+	isicom_normal.init_termios.c_cflag	= 
+				B9600 | CS8 | CREAD | HUPCL |CLOCAL;
+	isicom_normal.flags	= TTY_DRIVER_REAL_RAW;
+	isicom_normal.refcount	= &isicom_refcount;
+	
+	isicom_normal.table	= isicom_table;
+	isicom_normal.termios	= isicom_termios;
+	isicom_normal.termios_locked	= isicom_termios_locked;
+	
+	isicom_normal.open	= isicom_open;
+	isicom_normal.close	= isicom_close;
+	isicom_normal.write	= isicom_write;
+	isicom_normal.put_char	= isicom_put_char;
+	isicom_normal.flush_chars	= isicom_flush_chars;
+	isicom_normal.write_room	= isicom_write_room;
+	isicom_normal.chars_in_buffer	= isicom_chars_in_buffer;
+	isicom_normal.ioctl	= isicom_ioctl;
+	isicom_normal.set_termios	= isicom_set_termios;
+	isicom_normal.throttle	= isicom_throttle;
+	isicom_normal.unthrottle	= isicom_unthrottle;
+	isicom_normal.stop	= isicom_stop;
+	isicom_normal.start	= isicom_start;
+	isicom_normal.hangup	= isicom_hangup;
+	isicom_normal.flush_buffer	= isicom_flush_buffer;
+	
+	/*	callout device	*/
+	
+	isicom_callout	= isicom_normal;
+	isicom_callout.name	= "cum"; 
+	isicom_callout.major	= ISICOM_CMAJOR;
+	isicom_callout.subtype	= SERIAL_TYPE_CALLOUT;
+	
+	if ((error=tty_register_driver(&isicom_normal))!=0) {
+		printk(KERN_DEBUG "ISICOM: Couldn't register the dialin driver, error=%d\n",
+			error);
+		return error;
+	}
+	if ((error=tty_register_driver(&isicom_callout))!=0) {
+		tty_unregister_driver(&isicom_normal);
+		printk(KERN_DEBUG "ISICOM: Couldn't register the callout driver, error=%d\n",
+			error);
+		return error;	
+	}
+	return 0;
+}
+
+static void unregister_drivers(void)
+{
+	int error;
+	if ((error=tty_unregister_driver(&isicom_callout))!=0)
+		printk(KERN_DEBUG "ISICOM: couldn't unregister callout driver error=%d.\n",error);
+	if (tty_unregister_driver(&isicom_normal))
+		printk(KERN_DEBUG "ISICOM: couldn't unregister normal driver error=%d.\n",error);
+}
+
+static int register_isr(void)
+{
+	int count, done=0;
+	for (count=0; count < BOARD_COUNT; count++ ) {
+		if (isi_card[count].base) {
+			if (request_irq(isi_card[count].irq, isicom_interrupt, SA_INTERRUPT, ISICOM_NAME, NULL)) {
+				printk(KERN_WARNING "ISICOM: Could not install handler at Irq %d. Card%d will be disabled.\n",
+					isi_card[count].irq, count+1);
+				release_region(isi_card[count].base,16);
+				isi_card[count].base=0;
+			}
+			else {
+				printk(KERN_INFO "ISICOM: Card%d at 0x%x using irq %d.\n", 
+				count+1, isi_card[count].base, isi_card[count].irq); 
+				
+				irq_to_board[isi_card[count].irq]=&isi_card[count];
+				done++;
+			}
+		}	
+	}
+	return done;
+}
+
+static void unregister_isr(void)
+{
+	int count;
+	for (count=0; count < BOARD_COUNT; count++ ) 
+		if (isi_card[count].base) {
+			free_irq(isi_card[count].irq, NULL);
+#ifdef ISICOM_DEBUG			
+			printk(KERN_DEBUG "ISICOM: Irq %d released for Card%d.\n",isi_card[count].irq, count+1);
+#endif			
+		}
+}
+
+static int isicom_init(void)
+{
+	int card, channel, base;
+	struct isi_port * port;
+	unsigned long page;
+	
+	if (!tmp_buf) { 
+		page = get_free_page(GFP_KERNEL);
+	      	if (!page) {
+#ifdef ISICOM_DEBUG	      	
+	      		printk(KERN_DEBUG "ISICOM: Couldn't allocate page for tmp_buf.\n");
+#else
+			printk(KERN_ERR "ISICOM: Not enough memory...\n");
+#endif	      
+	      		return 0;
+	      	}	
+	      	tmp_buf = (unsigned char *) page;
+	}
+	
+	if (!register_ioregion()) 
+	{
+		printk(KERN_ERR "ISICOM: All required I/O space found busy.\n");
+		free_page((unsigned long)tmp_buf);
+		return 0;
+	}
+	if (register_drivers()) 
+	{
+		unregister_ioregion();
+		free_page((unsigned long)tmp_buf);
+		return 0;
+	}
+	if (!register_isr()) 
+	{
+		unregister_drivers();
+		/*  ioports already uregistered in register_isr */
+		free_page((unsigned long)tmp_buf);
+		return 0;		
+	}
+	
+	/* initialize bottom half  */
+	init_bh(ISICOM_BH, do_isicom_bh);
+
+
+	memset(isi_ports, 0, sizeof(isi_ports));
+	for (card = 0; card < BOARD_COUNT; card++) {
+		port = &isi_ports[card * 16];
+		isi_card[card].ports = port;
+		base = isi_card[card].base;
+		for (channel = 0; channel < 16; channel++, port++) {
+			port->magic = ISICOM_MAGIC;
+			port->card = &isi_card[card];
+			port->channel = channel;		
+			port->normal_termios = isicom_normal.init_termios;
+			port->callout_termios = isicom_callout.init_termios;
+		 	port->close_delay = 50 * HZ/100;
+		 	port->closing_wait = 3000 * HZ/100;
+			port->hangup_tq.routine = do_isicom_hangup;
+		 	port->hangup_tq.data = port;
+		 	port->bh_tqueue.routine = isicom_bottomhalf;
+		 	port->bh_tqueue.data = port;
+		 	port->status = 0;
+		 				
+			/*  . . .  */
+ 		}
+	} 
+	
+	return 1;	
+}
+
+/*
+ *	Insmod can set static symbols so keep these static
+ */
+ 
+static int io[4];
+static int irq[4];
+
+MODULE_AUTHOR("MultiTech");
+MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM_DESC(io, "I/O ports for the cards");
+MODULE_PARM(irq, "1-4i");
+MODULE_PARM_DESC(irq, "Interrupts for the cards");
+
+int init_module(void)
+{
+	int retval, card;
+
+	for(card=0; card < BOARD_COUNT; card++)
+	{	
+		isi_card[card].base=io[card];
+		isi_card[card].irq=irq[card];
+	}
+	
+	for (card=0 ;card < BOARD_COUNT; card++) {
+		if (!((isi_card[card].irq==2)||(isi_card[card].irq==3)||
+		    (isi_card[card].irq==4)||(isi_card[card].irq==5)||
+		    (isi_card[card].irq==7)||(isi_card[card].irq==10)||
+		    (isi_card[card].irq==11)||(isi_card[card].irq==12)||
+		    (isi_card[card].irq==15))) {
+			
+			if (isi_card[card].base) {
+				printk(KERN_ERR "ISICOM: Irq %d unsupported. Disabling Card%d...\n",
+					isi_card[card].irq, card+1);
+				isi_card[card].base=0;
+			}	
+		}
+	}	
+	
+	if (!(isi_card[0].base || isi_card[1].base || isi_card[2].base || isi_card[3].base)) {
+		printk(KERN_ERR "ISICOM: No valid card configuration. Driver cannot be initialized...\n"); 
+		return -EIO;
+	}		
+	retval=misc_register(&isiloader_device);
+	if (retval<0) {
+		printk(KERN_ERR "ISICOM: Unable to register firmware loader driver.\n");
+		return -EIO;
+	}
+	
+	if (!isicom_init()) {
+		if (misc_deregister(&isiloader_device)) 
+			printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+		return -EIO;
+	}
+	
+	init_timer(&tx);
+	tx.expires = jiffies + 1;
+	tx.data = 0;
+	tx.function = isicom_tx;
+	re_schedule = 1;
+	add_timer(&tx);
+	
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	re_schedule = 0;
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(HZ);
+	disable_bh(ISICOM_BH);
+	
+#ifdef ISICOM_DEBUG	
+	printk("ISICOM: isicom_tx tx_count = %ld.\n", tx_count);
+#endif	
+
+#ifdef ISICOM_DEBUG
+	printk("ISICOM: uregistering isr ...\n");
+#endif	
+	unregister_isr();
+
+#ifdef ISICOM_DEBUG	
+	printk("ISICOM: unregistering drivers ...\n");
+#endif
+	unregister_drivers();
+	
+#ifdef ISICOM_DEBUG	
+	printk("ISICOM: unregistering ioregion ...\n");
+#endif	
+	unregister_ioregion();	
+	
+#ifdef ISICOM_DEBUG	
+	printk("ISICOM: freeing tmp_buf ...\n");
+#endif	
+	free_page((unsigned long)tmp_buf);
+	
+#ifdef ISICOM_DEBUG		
+	printk("ISICOM: unregistering firmware loader ...\n");	
+#endif
+	if (misc_deregister(&isiloader_device))
+		printk(KERN_ERR "ISICOM: Unable to unregister Firmware Loader driver\n");
+}
diff -u --recursive --new-file v2.1.131/linux/drivers/char/joystick/Config.in linux/drivers/char/joystick/Config.in
--- v2.1.131/linux/drivers/char/joystick/Config.in	Wed Dec 16 10:32:54 1998
+++ linux/drivers/char/joystick/Config.in	Wed Dec 16 13:38:18 1998
@@ -10,9 +10,9 @@
 dep_tristate '   ThrustMaster DirectConnect joysticks and gamepads' CONFIG_JOY_THRUSTMASTER $CONFIG_JOYSTICK
 dep_tristate '   PDPI Lightning 4 gamecards' CONFIG_JOY_LIGHTNING $CONFIG_JOYSTICK
 if [ "$CONFIG_PARPORT" != "n" ]; then
-  dep_tristate '   NES, SNES, PSX, Multisystem joysticks and gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK
-  dep_tristate '   Sega, Multisystem joysticks and gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK
-  dep_tristate '   TurboGraFX Multisystem joystick interface' CONFIG_JOY_TURBOGRAFX $CONFIG_JOYSTICK
+  dep_tristate '   NES, SNES, PSX, Multisystem joysticks and gamepads' CONFIG_JOY_CONSOLE $CONFIG_JOYSTICK $CONFIG_PARPORT
+  dep_tristate '   Sega, Multisystem joysticks and gamepads' CONFIG_JOY_DB9 $CONFIG_JOYSTICK $CONFIG_PARPORT
+  dep_tristate '   TurboGraFX Multisystem joystick interface' CONFIG_JOY_TURBOGRAFX $CONFIG_JOYSTICK $CONFIG_PARPORT
 fi  
 if [ "$CONFIG_AMIGA" = "y" ]; then
   dep_tristate '   Amiga joysticks' CONFIG_JOY_AMIGA $CONFIG_JOYSTICK
diff -u --recursive --new-file v2.1.131/linux/drivers/char/mac_SCC.c linux/drivers/char/mac_SCC.c
--- v2.1.131/linux/drivers/char/mac_SCC.c	Fri Oct  9 13:27:08 1998
+++ linux/drivers/char/mac_SCC.c	Fri Dec 18 09:36:05 1998
@@ -198,18 +198,6 @@
 };
 
 /*
- * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the memcpy_fromfs blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char tmp_buf[4096]; /* This is cheating */
-static struct semaphore tmp_buf_sem = MUTEX;
-
-/*
  * This is used to figure out the divisor speeds and the timeouts
  */
 static int baud_table[] = {
@@ -771,7 +759,7 @@
 
 	/* If console serial line, then enable interrupts. */
 	if (info->private->is_cons) {
-		printk("mac_SCC: console line %lx; enabling interrupt!\n", info);
+		printk("mac_SCC: console line %d; enabling interrupt!\n", info->line);
 		write_zsreg(info->private->zs_channel, R1,
 			    (EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB));
 		write_zsreg(info->private->zs_channel, R9, (NV | MIE));
@@ -784,7 +772,7 @@
 	 * client attached to us asynchronously.
 	 */
 	if (info->private->kgdb_channel) {
-		printk("mac_SCC: kgdb line %lx; enabling interrupt!\n", info);
+		printk("mac_SCC: kgdb line %d; enabling interrupt!\n", info->line);
 		kgdb_chaninit(info, 1, info->private->zs_baud);
 	}
 	/* Report settings (in m68kserial.c) */
@@ -1141,8 +1129,6 @@
 static void SCC_get_serial_info(struct m68k_async_struct * info,
 			   struct serial_struct * retinfo)
 {
-	struct serial_struct tmp;
-  
 	retinfo->baud_base = info->baud_base;
 	retinfo->custom_divisor = info->custom_divisor;
 }
@@ -1190,8 +1176,7 @@
 static int SCC_set_modem_info(struct m68k_async_struct *info, 
 			      int new_dtr, int new_rts)
 {
-	int error;
-	unsigned int arg, bits;
+	unsigned int bits;
 
 	bits = (new_rts ? RTS: 0) + (new_dtr ? DTR: 0);
 	info->private->curregs[5] = (info->private->curregs[5] & ~(DTR | RTS)) | bits;
@@ -1231,7 +1216,6 @@
 	            unsigned long arg)
 {
 	int error;
-	int retval;
 
 	switch (cmd) {
 		case TIOCSERGETLSR: /* Get line status register */
@@ -1315,9 +1299,9 @@
 				ZS_CONTROL+ZS_MOVE*n;
 		zs_channels[n].data = (volatile unsigned char *)ZS_DATA+ZS_MOVE*n;
 #else
-		zs_channels[n].control = (volatile unsigned char *)
+		zs_channels[n].control = (volatile unsigned char *) /* 2, 0 */
 			(mac_bi_data.sccbase+ZS_CH_A_FIRST)+ZS_MOVE*n;
-		zs_channels[n].data = (volatile unsigned char *)
+		zs_channels[n].data = (volatile unsigned char *) /* 6, 4 */
 			(mac_bi_data.sccbase+ZS_CH_A_FIRST+ZS_DATA_MOVE)+ZS_MOVE*n;
 #endif
 		zs_soft[n].private = &zs_soft_private[n];
@@ -1405,8 +1389,8 @@
 rs_cons_check(struct m68k_async_struct *ss, int channel)
 {
 	int i, o, io;
-	static consout_registered = 0;
-	static msg_printed = 0;
+	static int consout_registered = 0;
+	static int msg_printed = 0;
 
 	i = o = io = 0;
 
@@ -1458,10 +1442,9 @@
 /* rs_init inits the driver */
 int mac_SCC_init(void)
 {
-	int channel, line, nr = 0, i;
+	int channel, line, nr = 0;
 	unsigned long flags;
 	struct serial_struct req;
-	struct m68k_async_struct *info;
 
 	printk("Mac68K Z8530 serial driver version 1.01\n");
 
@@ -1486,7 +1469,7 @@
 	for (channel = 0; channel < zs_channels_found; ++channel) {
 		req.line = channel;
 		req.type = SER_SCC_MAC;
-		req.port = zs_soft[channel].private->zs_channel->control;
+		req.port = (int) zs_soft[channel].private->zs_channel->control;
 
 		if ((line = register_serial( &req )) >= 0) {
 			SCC_init_port( &rs_table[line], req.type, line );
diff -u --recursive --new-file v2.1.131/linux/drivers/char/macmouse.c linux/drivers/char/macmouse.c
--- v2.1.131/linux/drivers/char/macmouse.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/macmouse.c	Wed Dec 31 16:00:00 1969
@@ -1,312 +0,0 @@
-/*
- * Macintosh ADB Mouse driver for Linux
- *
- * 27 Oct 1997 Michael Schmitz
- *
- * Apple mouse protocol according to:
- *
- * Device code shamelessly stolen from:
- */
-/*
- * Atari Mouse Driver for Linux
- * by Robert de Vries (robert@and.nl) 19Jul93
- *
- * 16 Nov 1994 Andreas Schwab
- * Compatibility with busmouse
- * Support for three button mouse (shamelessly stolen from MiNT)
- * third button wired to one of the joystick directions on joystick 1
- *
- * 1996/02/11 Andreas Schwab
- * Module support
- * Allow multiple open's
- */
-
-#include <linux/module.h>
-
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/mm.h>
-#include <linux/random.h>
-#include <linux/poll.h>
-#include <linux/init.h>
-
-#include <asm/setup.h>
-#include <asm/mac_mouse.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-
-static struct mouse_status mouse;
-static int mac_mouse_x_threshold = 2, mac_mouse_y_threshold = 2;
-static int mac_mouse_buttons = 0;
-
-extern void (*mac_mouse_interrupt_hook) (char *, int);
-extern int mac_emulate_button2;
-extern int mac_emulate_button3;
-
-extern int console_loglevel;
-
-/*
- *	XXX: need to figure out what ADB mouse packets mean ... 
- *	This is the stuff stolen from the Atari driver ...
- */
-static void mac_mouse_interrupt(char *buf, int nb)
-{
-    static int buttons = 7;	/* all mouse buttons _up_ !! */
-
-  /*
-    Handler 1 -- 100cpi original Apple mouse protocol.
-    Handler 2 -- 200cpi original Apple mouse protocol.
-
-    For Apple's standard one-button mouse protocol the data array will
-    contain the following values:
-
-                BITS    COMMENTS
-    data[0] = 0000 0000 ADB packet identifer.
-    data[1] = ???? ???? (?)
-    data[2] = ???? ??00 Bits 0-1 should be zero for a mouse device.
-    data[3] = bxxx xxxx First button and x-axis motion.
-    data[4] = byyy yyyy Second button and y-axis motion.
-
-    NOTE: data[0] is confirmed by the parent function and need not be
-    checked here.
-  */
-
-  /*
-    Handler 4 -- Apple Extended mouse protocol.
-
-    For Apple's 3-button mouse protocol the data array will contain the
-    following values:
-
-		BITS    COMMENTS
-    data[0] = 0000 0000 ADB packet identifer.
-    data[1] = 0100 0000 Extended protocol register.
-	      Bits 6-7 are the device id, which should be 1.
-	      Bits 4-5 are resolution which is in "units/inch".
-	      The Logitech MouseMan returns these bits clear but it has
-	      200/300cpi resolution.
-	      Bits 0-3 are unique vendor id.
-    data[2] = 0011 1100 Bits 0-1 should be zero for a mouse device.
-	      Bits 2-3 should be 8 + 4.
-		      Bits 4-7 should be 3 for a mouse device.
-    data[3] = bxxx xxxx Left button and x-axis motion.
-    data[4] = byyy yyyy Second button and y-axis motion.
-    data[5] = byyy bxxx Third button and fourth button.  
-    	      Y is additiona. high bits of y-axis motion.  
-    	      X is additional high bits of x-axis motion.
-
-    NOTE: data[0] and data[2] are confirmed by the parent function and
-    need not be checked here.
-  */
-
-    /*
-     * 'buttons' here means 'button down' states!
-     * Button 1 (left)  : bit 2, busmouse button 3
-     * Button 2 (right) : bit 0, busmouse button 1
-     * Button 3 (middle): bit 1, busmouse button 2
-     */
-
-    /* x/y and buttons swapped */
-    
-    if (buf[0] ==  0)	{				/* real packet : use buttons? */
-#ifdef DEBUG_ADBMOUSE
-	if (console_loglevel >= 8)
-	    printk("mac_mouse: real data; "); 
-#endif
-	/* button 1 (left, bit 2) : always significant ! */
-	buttons = (buttons&3) | (buf[3] & 0x80 ? 4 : 0); /* 1+2 unchanged */
-	/* button 2 (right, bit 0) present ? */
-	if ( !mac_emulate_button2 ) 
-	    buttons = (buttons&6) | (buf[4] & 0x80 ? 1 : 0); /* 2+3 unchanged */
-	/* button 2 (middle) present? */
-	/* data valid only if extended mouse format ! (buf[3] = 0 else)*/
-	if ( !mac_emulate_button3 && buf[1]&0x40 )
-	    buttons = (buttons&5) | (buf[5] & 0x80 ? 2 : 0); /* 1+3 unchanged */
-    } else {					/* fake packet : use 2+3 */
-#ifdef DEBUG_ADBMOUSE
-	if (console_loglevel >= 8)
-	    printk("mac_mouse: fake data; "); 
-#endif
-	/* we only see state changes here, but the fake driver takes care
-	 * to preserve state... button 1 state must stay unchanged! */
-	buttons = (buttons&4) | ((buf[4] & 0x80 ? 1 : 0) | (buf[5] & 0x80 ? 2 : 0));
-    }
-
-    add_mouse_randomness(((~buttons & 7) << 16) + ((buf[2]&0x7f) << 8) + (buf[1]&0x7f));
-    mouse.buttons = buttons & 7;
-    mouse.dx += ((buf[4]&0x7f) < 64 ? (buf[4]&0x7f) : (buf[4]&0x7f)-128 );
-    mouse.dy -= ((buf[3]&0x7f) < 64 ? (buf[3]&0x7f) : (buf[3]&0x7f)-128 );
-
-#ifdef DEBUG_ADBMOUSE
-    if (console_loglevel >= 8)
-        printk(" %X %X %X buttons %x dx %d dy %d \n", 
-               buf[3], buf[4], buf[5], mouse.buttons, mouse.dx, mouse.dy);
-#endif
- 
-    mouse.ready = 1;
-    wake_up_interruptible(&mouse.wait);
-    if (mouse.fasyncptr)
-	kill_fasync(mouse.fasyncptr, SIGIO);
-
-}
-
-static int fasync_mouse(int fd, struct file *filp, int on)
-{
-	int retval;
-
-	retval = fasync_helper(fd, filp, on, &mouse.fasyncptr);
-	if (retval < 0)
-		return retval;
-	return 0;
-}
-
-static int release_mouse(struct inode *inode, struct file *file)
-{
-    fasync_mouse(-1, file, 0);
-    if (--mouse.active)
-      return 0;
-
-    mac_mouse_interrupt_hook = NULL;
-    MOD_DEC_USE_COUNT;
-    return 0;
-}
-
-static int open_mouse(struct inode *inode, struct file *file)
-{
-    if (mouse.active++)
-	return 0;
-	
-    mouse.ready = 0;
-
-    mouse.dx = mouse.dy = 0;
-    mac_mouse_buttons = 0;
-    MOD_INC_USE_COUNT;
-    mac_mouse_interrupt_hook = mac_mouse_interrupt;
-    return 0;
-}
-
-static ssize_t write_mouse(struct file *file, const char *buffer,
-			   size_t count, loff_t *ppos)
-{
-    return -EINVAL;
-}
-
-static ssize_t read_mouse(struct file *file, char *buffer, size_t count,
-			  loff_t *ppos)
-{
-    int dx, dy, buttons;
-
-    if (count < 3)
-	return -EINVAL;
-    if (!mouse.ready)
-	return -EAGAIN;
-    dx = mouse.dx;
-    dy = mouse.dy;
-    buttons = mouse.buttons;
-    if (dx > 127)
-      dx = 127;
-    else if (dx < -128)
-      dx = -128;
-    if (dy > 127)
-      dy = 127;
-    else if (dy < -128)
-      dy = -128;
-    mouse.dx -= dx;
-    mouse.dy -= dy;
-    if (mouse.dx == 0 && mouse.dy == 0)
-      mouse.ready = 0;
-    if (put_user(buttons | 0x80, buffer++) ||
-	put_user((char) dx, buffer++) ||
-	put_user((char) dy, buffer++))
-      return -EFAULT;
-    if (count > 3)
-      if (clear_user(buffer, count - 3))
-	return -EFAULT;
-    return count;
-}
-
-static unsigned int mouse_poll(struct file *file, poll_table *wait)
-{
-	poll_wait(file, &mouse.wait, wait);
-	if (mouse.ready)
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-struct file_operations mac_mouse_fops = {
-    NULL,		/* mouse_seek */
-    read_mouse,
-    write_mouse,
-    NULL,		/* mouse_readdir */
-    mouse_poll,
-    NULL,		/* mouse_ioctl */
-    NULL,		/* mouse_mmap */
-    open_mouse,
-    NULL,		/* flush */
-    release_mouse,
-    NULL,
-    fasync_mouse,
-};
-
-#define ADB_MOUSE_MINOR	10
-
-static struct miscdevice mac_mouse = {
-    ADB_MOUSE_MINOR, "adbmouse", &mac_mouse_fops
-};
-
-__initfunc(int mac_mouse_init(void))
-{
-    mouse.active = 0;
-    mouse.ready = 0;
-    mouse.wait = NULL;
-
-    if (!MACH_IS_MAC)
-	return -ENODEV;
-
-    printk(KERN_INFO "Macintosh ADB mouse installed.\n");
-    misc_register(&mac_mouse);
-    return 0;
-}
-
-
-#define	MIN_THRESHOLD 1
-#define	MAX_THRESHOLD 20	/* more seems not reasonable... */
-
-__initfunc(void mac_mouse_setup(char *str, int *ints))
-{
-    if (ints[0] < 1) {
-	printk( "mac_mouse_setup: no arguments!\n" );
-	return;
-    }
-    else if (ints[0] > 2) {
-	printk( "mac_mouse_setup: too many arguments\n" );
-    }
-
-    if (ints[1] < MIN_THRESHOLD || ints[1] > MAX_THRESHOLD)
-	printk( "mac_mouse_setup: bad threshold value (ignored)\n" );
-    else {
-	mac_mouse_x_threshold = ints[1];
-	mac_mouse_y_threshold = ints[1];
-	if (ints[0] > 1) {
-	    if (ints[2] < MIN_THRESHOLD || ints[2] > MAX_THRESHOLD)
-		printk("mac_mouse_setup: bad threshold value (ignored)\n" );
-	    else
-		mac_mouse_y_threshold = ints[2];
-	}
-    }
-	
-}
-
-#ifdef MODULE
-#include <asm/setup.h>
-
-int init_module(void)
-{
-    return mac_mouse_init();
-}
-
-void cleanup_module(void)
-{
-    misc_deregister(&mac_mouse);
-}
-#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.1.131/linux/drivers/char/mem.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/char/mem.c	Wed Dec 16 13:39:11 1998
@@ -21,6 +21,7 @@
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/joystick.h>
+#include <linux/i2c.h>
 
 #include <asm/uaccess.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.1.131/linux/drivers/char/msbusmouse.c linux/drivers/char/msbusmouse.c
--- v2.1.131/linux/drivers/char/msbusmouse.c	Wed Aug 26 11:37:37 1998
+++ linux/drivers/char/msbusmouse.c	Wed Dec 16 13:39:11 1998
@@ -51,6 +51,10 @@
 static struct mouse_status mouse;
 static int mouse_irq = MOUSE_IRQ;
 
+#ifdef MODULE
+MODULE_PARM(mouse_irq, "i");
+#endif
+
 __initfunc(void msmouse_setup(char *str, int *ints))
 {
 	if (ints[0] > 0)
diff -u --recursive --new-file v2.1.131/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.1.131/linux/drivers/char/pc_keyb.c	Sun Nov  8 14:02:55 1998
+++ linux/drivers/char/pc_keyb.c	Wed Dec 16 13:39:11 1998
@@ -64,7 +64,7 @@
 static volatile unsigned char resend = 0;
 
 
-#if defined CONFIG_PSMOUSE
+#if defined(CONFIG_PSMOUSE)
 /*
  *	PS/2 Auxiliary Device
  */
diff -u --recursive --new-file v2.1.131/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.1.131/linux/drivers/char/serial.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/char/serial.c	Tue Dec 22 08:30:16 1998
@@ -154,7 +154,7 @@
 #endif
 	
 static char *serial_name = "Serial driver";
-static char *serial_version = "4.26";
+static char *serial_version = "4.27";
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
@@ -180,7 +180,7 @@
 
 static unsigned detect_uart_irq (struct serial_state * state);
 static void autoconfig(struct serial_state * info);
-static void change_speed(struct async_struct *info);
+static void change_speed(struct async_struct *info, struct termios *old);
 static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
 
 /*
@@ -194,7 +194,7 @@
 	{ "16550", 1, 0 }, 
 	{ "16550A", 16, UART_CLEAR_FIFO | UART_USE_FIFO }, 
 	{ "cirrus", 1, 0 }, 
-	{ "ST16650", 1, UART_CLEAR_FIFO |UART_STARTECH }, 
+	{ "ST16650", 1, UART_CLEAR_FIFO | UART_STARTECH }, 
 	{ "ST16650V2", 32, UART_CLEAR_FIFO | UART_USE_FIFO |
 		  UART_STARTECH }, 
 	{ "TI16750", 64, UART_CLEAR_FIFO | UART_USE_FIFO},
@@ -1110,7 +1110,7 @@
 	/*
 	 * and set the speed of the serial port
 	 */
-	change_speed(info);
+	change_speed(info, 0);
 
 	info->flags |= ASYNC_INITIALIZED;
 	restore_flags(flags);
@@ -1233,7 +1233,8 @@
  * This routine is called to set the UART divisor registers to match
  * the specified baud rate for a serial port.
  */
-static void change_speed(struct async_struct *info)
+static void change_speed(struct async_struct *info,
+			 struct termios *old_termios)
 {
 	unsigned short port;
 	int	quot = 0, baud_base, baud;
@@ -1284,7 +1285,25 @@
 		else if (baud)
 			quot = baud_base / baud;
 	}
-	/* If the quotient is ever zero, default to 9600 bps */
+	/* If the quotient is zero refuse the change */
+	if (!quot && old_termios) {
+		info->tty->termios->c_cflag &= ~CBAUD;
+		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
+		baud = tty_get_baud_rate(info->tty);
+		if (!baud)
+			baud = 9600;
+		if (baud == 38400 &&
+		    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
+			quot = info->state->custom_divisor;
+		else {
+			if (baud == 134)
+				/* Special case since 134 is really 134.5 */
+				quot = (2*baud_base / 269);
+			else if (baud)
+				quot = baud_base / baud;
+		}
+	}
+	/* As a last resort, if the quotient is zero, default to 9600 bps */
 	if (!quot)
 		quot = baud_base / 9600;
 	info->quot = quot;
@@ -1653,8 +1672,8 @@
 			return -EPERM;
 		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
 			       (new_serial.flags & ASYNC_USR_MASK));
-		info->flags = ((state->flags & ~ASYNC_USR_MASK) |
-			       (info->flags & ASYNC_USR_MASK));
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
 		state->custom_divisor = new_serial.custom_divisor;
 		goto check_and_exit;
 	}
@@ -1733,7 +1752,7 @@
 				info->tty->alt_speed = 230400;
 			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
 				info->tty->alt_speed = 460800;
-			change_speed(info);
+			change_speed(info, 0);
 		}
 	} else
 		retval = startup(info);
@@ -2003,7 +2022,6 @@
 			       "driver!!\n");
 		}
 	}
-
 	return 0;
 }
 #endif
@@ -2150,7 +2168,7 @@
 		== RELEVANT_IFLAG(old_termios->c_iflag)))
 	  return;
 
-	change_speed(info);
+	change_speed(info, old_termios);
 
 	/* Handle transition to B0 status */
 	if ((old_termios->c_cflag & CBAUD) &&
@@ -2645,13 +2663,13 @@
 			*tty->termios = info->state->normal_termios;
 		else 
 			*tty->termios = info->state->callout_termios;
-		change_speed(info);
+		change_speed(info, 0);
 	}
 #ifdef CONFIG_SERIAL_CONSOLE
 	if (sercons.cflag && sercons.index == line) {
 		tty->termios->c_cflag = sercons.cflag;
 		sercons.cflag = 0;
-		change_speed(info);
+		change_speed(info, 0);
 	}
 #endif
 	info->session = current->session;
@@ -2881,8 +2899,8 @@
  * This routine is called by rs_init() to initialize a specific serial
  * port.  It determines what type of UART chip this serial port is
  * using: 8250, 16450, 16550, 16550A.  The important question is
- * whether or not this UART is a 16550A or not, since this will
- * determine whether or not we can use its FIFO features or not.
+ * whether or not this UART is a 16550A, since this will determine
+ * whether or not we can use its FIFO features.
  */
 static void autoconfig(struct serial_state * state)
 {
diff -u --recursive --new-file v2.1.131/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v2.1.131/linux/drivers/char/tty_ioctl.c	Sun Nov  8 14:02:56 1998
+++ linux/drivers/char/tty_ioctl.c	Thu Dec 17 16:11:37 1998
@@ -52,7 +52,6 @@
 	if (!tty->driver.chars_in_buffer)
 		return;
 	add_wait_queue(&tty->write_wait, &wait);
-	current->counter = 0;	/* make us low-priority */
 	if (!timeout)
 		timeout = MAX_SCHEDULE_TIMEOUT;
 	do {
diff -u --recursive --new-file v2.1.131/linux/drivers/fc4/fc.c linux/drivers/fc4/fc.c
--- v2.1.131/linux/drivers/fc4/fc.c	Thu Apr 23 20:21:33 1998
+++ linux/drivers/fc4/fc.c	Wed Dec 16 13:39:11 1998
@@ -1,7 +1,7 @@
 /* fc.c: Generic Fibre Channel and FC4 SCSI driver.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997,1998 Jiri Hanika (geo@ff.cuni.cz)
+ * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
  *
  * Sources:
  *	Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
diff -u --recursive --new-file v2.1.131/linux/drivers/fc4/fcp_scsi.h linux/drivers/fc4/fcp_scsi.h
--- v2.1.131/linux/drivers/fc4/fcp_scsi.h	Thu Apr 23 20:21:33 1998
+++ linux/drivers/fc4/fcp_scsi.h	Wed Dec 16 13:39:11 1998
@@ -1,7 +1,7 @@
 /* fcp_scsi.h: Generic SCSI on top of FC4 - interface defines.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1998 Jiri Hanika (geo@ff.cuni.cz)
+ * Copyright (C) 1998 Jirka Hanika (geo@ff.cuni.cz)
  */
 
 #ifndef _FCP_SCSI_H
diff -u --recursive --new-file v2.1.131/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c
--- v2.1.131/linux/drivers/fc4/soc.c	Thu Aug  6 14:06:31 1998
+++ linux/drivers/fc4/soc.c	Wed Dec 16 13:39:11 1998
@@ -1,7 +1,7 @@
 /* soc.c: Sparc SUNW,soc (Serial Optical Channel) Fibre Channel Sbus adapter support.
  *
  * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
- * Copyright (C) 1997,1998 Jiri Hanika (geo@ff.cuni.cz)
+ * Copyright (C) 1997,1998 Jirka Hanika (geo@ff.cuni.cz)
  *
  * Sources:
  *	Fibre Channel Physical & Signaling Interface (FC-PH), dpANS, 1994
@@ -20,7 +20,7 @@
  */
 
 static char *version =
-        "soc.c:v1.2 27/Feb/98 Jakub Jelinek (jj@sunsite.mff.cuni.cz), Jiri Hanika (geo@ff.cuni.cz)\n";
+        "soc.c:v1.2 27/Feb/98 Jakub Jelinek (jj@sunsite.mff.cuni.cz), Jirka Hanika (geo@ff.cuni.cz)\n";
 
 #include <linux/module.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.1.131/linux/drivers/macintosh/mediabay.c linux/drivers/macintosh/mediabay.c
--- v2.1.131/linux/drivers/macintosh/mediabay.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/macintosh/mediabay.c	Mon Dec 21 08:37:28 1998
@@ -180,7 +180,7 @@
 {
 #ifdef CONFIG_BLK_DEV_IDE
 	int	i;
-	
+
 	for (i=0; i<media_bay_count; i++)
 		if (which_bay == media_bays[i].dev_node)
 		{
@@ -196,9 +196,9 @@
 int
 check_media_bay_by_base(unsigned long base, int what)
 {
+#ifdef CONFIG_BLK_DEV_IDE
 	int	i;
 
-#ifdef CONFIG_BLK_DEV_IDE
 	for (i=0; i<media_bay_count; i++)
 		if (base == media_bays[i].cd_base)
 		{
@@ -216,9 +216,9 @@
 media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
 	int irq, int index)
 {
-	int	i;
-	
 #ifdef CONFIG_BLK_DEV_IDE
+	int	i;
+
 	for (i=0; i<media_bay_count; i++)
 		if (which_bay == media_bays[i].dev_node)
 		{
diff -u --recursive --new-file v2.1.131/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.1.131/linux/drivers/macintosh/via-pmu.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/macintosh/via-pmu.c	Mon Dec 21 08:37:28 1998
@@ -523,7 +523,7 @@
 	int intr;
 	int nloop = 0;
 
-	while ((intr = (in_8(&via[IFR]) & (SR_INT | CB1_INT))) != 0) {
+	while ((intr = in_8(&via[IFR])) != 0) {
 		if (++nloop > 1000) {
 			printk(KERN_DEBUG "PMU: stuck in intr loop, "
 			       "intr=%x pmu_state=%d\n", intr, pmu_state);
@@ -534,6 +534,12 @@
 		else if (intr & CB1_INT) {
 			adb_int_pending = 1;
 			out_8(&via[IFR], CB1_INT);
+		} else
+		{
+			/* -- Disabled printk, will happen _really_ often on
+				  PowerBooks ((CB2 interrupts) --
+			printk(KERN_DEBUG "PMU: spurrious interrupt intr=%x\n", intr); */
+			out_8(&via[IFR], intr);
 		}
 	}
 	if (pmu_state == idle) {
@@ -750,7 +756,8 @@
 
 	_disable_interrupts();
 	
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT);
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+					PMU_INT_TICK );
 	while(!req.complete)
 		pmu_poll();
 	
@@ -768,7 +775,8 @@
 
 	_disable_interrupts();
 	
-	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, CB1_INT);
+	pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, PMU_INT_ADB |
+					PMU_INT_TICK );
 	while(!req.complete)
 		pmu_poll();
 
diff -u --recursive --new-file v2.1.131/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.1.131/linux/drivers/net/3c503.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/net/3c503.c	Wed Dec 16 13:35:49 1998
@@ -684,7 +684,6 @@
 			void *priv = dev->priv;
 			/* NB: el2_close() handles free_irq */
 			release_region(dev->base_addr, EL2_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v2.1.131/linux/drivers/net/3c505.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/3c505.c	Thu Dec 17 09:03:57 1998
@@ -266,12 +266,12 @@
 
 static inline int get_status(unsigned int base_addr)
 {
-	int timeout = jiffies + 10;
+	int timeout = jiffies + 10*HZ/100;
 	register int stat1;
 	do {
 		stat1 = inb_status(base_addr);
-	} while (stat1 != inb_status(base_addr) && jiffies < timeout);
-	if (jiffies >= timeout)
+	} while (stat1 != inb_status(base_addr) && time_before(jiffies, timeout));
+	if (time_after_eq(jiffies, timeout))
 		TIMEOUT_MSG(__LINE__);
 	return stat1;
 }
@@ -296,23 +296,23 @@
 	if (inb_status(dev->base_addr) & ACRF) {
 		do {
 			inb_command(dev->base_addr);
-			timeout = jiffies + 2;
-			while ((jiffies <= timeout) && !(inb_status(dev->base_addr) & ACRF));
+			timeout = jiffies + 2*HZ/100;
+			while (time_before_eq(jiffies, timeout) && !(inb_status(dev->base_addr) & ACRF));
 		} while (inb_status(dev->base_addr) & ACRF);
 		set_hsf(dev, HSF_PCB_NAK);
 	}
 	outb_control(adapter->hcr_val | ATTN | DIR, dev);
-	timeout = jiffies + 1;
-	while (jiffies <= timeout);
+	timeout = jiffies + 1*HZ/100;
+	while (time_before_eq(jiffies, timeout));
 	outb_control(adapter->hcr_val & ~ATTN, dev);
-	timeout = jiffies + 1;
-	while (jiffies <= timeout);
+	timeout = jiffies + 1*HZ/100;
+	while (time_before_eq(jiffies, timeout));
 	outb_control(adapter->hcr_val | FLSH, dev);
-	timeout = jiffies + 1;
-	while (jiffies <= timeout);
+	timeout = jiffies + 1*HZ/100;
+	while (time_before_eq(jiffies, timeout));
 	outb_control(adapter->hcr_val & ~FLSH, dev);
-	timeout = jiffies + 1;
-	while (jiffies <= timeout);
+	timeout = jiffies + 1*HZ/100;
+	while (time_before_eq(jiffies, timeout));
 
 	outb_control(orig_hcr, dev);
 	if (!start_receive(dev, &adapter->tx_pcb))
@@ -326,7 +326,7 @@
 static inline void check_3c505_dma(struct device *dev)
 {
 	elp_device *adapter = dev->priv;
-	if (adapter->dmaing && (jiffies > (adapter->current_dma.start_time + 10))) {
+	if (adapter->dmaing && time_after(jiffies, adapter->current_dma.start_time + 10)) {
 		unsigned long flags, f;
 		printk("%s: DMA %s timed out, %d bytes left\n", dev->name, adapter->current_dma.direction ? "download" : "upload", get_dma_residue(dev->dma));
 		save_flags(flags);
@@ -350,7 +350,7 @@
 {
 	unsigned int timeout;
 	outb_command(byte, base_addr);
-	for (timeout = jiffies + 5; jiffies < timeout;) {
+	for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
 		if (inb_status(base_addr) & HCRE)
 			return FALSE;
 	}
@@ -448,7 +448,7 @@
 	/* now wait for the acknowledgement */
 	sti();
 
-	for (timeout = jiffies + 5; jiffies < timeout;) {
+	for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {
 		switch (GET_ASF(dev->base_addr)) {
 		case ASF_PCB_ACK:
 			adapter->send_pcb_semaphore = 0;
@@ -499,18 +499,18 @@
 	set_hsf(dev, 0);
 
 	/* get the command code */
-	timeout = jiffies + 2;
-	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout);
-	if (jiffies >= timeout) {
+	timeout = jiffies + 2*HZ/100;
+	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
+	if (time_after_eq(jiffies, timeout)) {
 		TIMEOUT_MSG(__LINE__);
 		return FALSE;
 	}
 	pcb->command = inb_command(dev->base_addr);
 
 	/* read the data length */
-	timeout = jiffies + 3;
-	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout);
-	if (jiffies >= timeout) {
+	timeout = jiffies + 3*HZ/100;
+	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));
+	if (time_after_eq(jiffies, timeout)) {
 		TIMEOUT_MSG(__LINE__);
 		printk("%s: status %02x\n", dev->name, stat);
 		return FALSE;
@@ -738,8 +738,8 @@
 		/*
 		 * receive a PCB from the adapter
 		 */
-		timeout = jiffies + 3;
-		while ((inb_status(dev->base_addr) & ACRF) != 0 && jiffies < timeout) {
+		timeout = jiffies + 3*HZ/100;
+		while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {
 			if (receive_pcb(dev, &adapter->irx_pcb)) {
 				switch (adapter->irx_pcb.command) {
 				case 0:
@@ -971,8 +971,8 @@
 		printk("%s: couldn't send memory configuration command\n", dev->name);
 	else {
 		int timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && jiffies < timeout);
-		if (jiffies >= timeout)
+		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));
+		if (time_after_eq(jiffies, timeout))
 			TIMEOUT_MSG(__LINE__);
 	}
 
@@ -990,8 +990,8 @@
 		printk("%s: couldn't send 82586 configure command\n", dev->name);
 	else {
 		int timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout);
-		if (jiffies >= timeout)
+		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
+		if (time_after_eq(jiffies, timeout))
 			TIMEOUT_MSG(__LINE__);
 	}
 
@@ -1177,8 +1177,8 @@
 		printk("%s: couldn't send get statistics command\n", dev->name);
 	else {
 		int timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && jiffies < timeout);
-		if (jiffies >= timeout) {
+		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));
+		if (time_after_eq(jiffies, timeout)) {
 			TIMEOUT_MSG(__LINE__);
 			return &adapter->stats;
 		}
@@ -1270,8 +1270,8 @@
 			printk("%s: couldn't send set_multicast command\n", dev->name);
 		else {
 			int timeout = jiffies + TIMEOUT;
-			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && jiffies < timeout);
-			if (jiffies >= timeout) {
+			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));
+			if (time_after_eq(jiffies, timeout)) {
 				TIMEOUT_MSG(__LINE__);
 			}
 		}
@@ -1294,8 +1294,8 @@
 		printk("%s: couldn't send 82586 configure command\n", dev->name);
 	else {
 		int timeout = jiffies + TIMEOUT;
-		while (adapter->got[CMD_CONFIGURE_82586] == 0 && jiffies < timeout);
-		if (jiffies >= timeout)
+		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));
+		if (time_after_eq(jiffies, timeout))
 			TIMEOUT_MSG(__LINE__);
 	}
 }
@@ -1371,8 +1371,8 @@
 	if (orig_HSR & DIR) {
 		/* If HCR.DIR is up, we pull it down. HSR.DIR should follow. */
 		outb(0, dev->base_addr + PORT_CONTROL);
-		timeout = jiffies + 30;
-		while (jiffies < timeout);
+		timeout = jiffies + 30*HZ/100;
+		while (time_before(jiffies, timeout));
 		restore_flags(flags);
 		if (inb_status(addr) & DIR) {
 			if (elp_debug > 0)
@@ -1382,8 +1382,8 @@
 	} else {
 		/* If HCR.DIR is down, we pull it up. HSR.DIR should follow. */
 		outb(DIR, dev->base_addr + PORT_CONTROL);
-		timeout = jiffies + 30;
-		while (jiffies < timeout);
+		timeout = jiffies + 30*HZ/100;
+		while (time_before(jiffies, timeout));
 		restore_flags(flags);
 		if (!(inb_status(addr) & DIR)) {
 			if (elp_debug > 0)
@@ -1479,13 +1479,13 @@
 		/* First try to write just one byte, to see if the card is
 		 * responding at all normally.
 		 */
-		timeout = jiffies + 5;
+		timeout = jiffies + 5*HZ/100;
 		okay = 0;
-		while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE));
+		while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
 		if ((inb_status(dev->base_addr) & HCRE)) {
 			outb_command(0, dev->base_addr);	/* send a spurious byte */
-			timeout = jiffies + 5;
-			while (jiffies < timeout && !(inb_status(dev->base_addr) & HCRE));
+			timeout = jiffies + 5*HZ/100;
+			while (time_before(jiffies, timeout) && !(inb_status(dev->base_addr) & HCRE));
 			if (inb_status(dev->base_addr) & HCRE)
 				okay = 1;
 		}
@@ -1499,8 +1499,8 @@
 				 * Give it the benefit of the doubt for 10 seconds.
 				 */
 				printk("assuming 3c505 still starting\n");
-				timeout = jiffies + 10 * HZ;
-				while (jiffies < timeout && (inb_status(dev->base_addr) & 7));
+				timeout = jiffies + 10*HZ;
+				while (time_before(jiffies, timeout) && (inb_status(dev->base_addr) & 7));
 				if (inb_status(dev->base_addr) & 7) {
 					printk("%s: 3c505 failed to start\n", dev->name);
 				} else {
diff -u --recursive --new-file v2.1.131/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.1.131/linux/drivers/net/3c509.c	Sun Nov  8 14:02:59 1998
+++ linux/drivers/net/3c509.c	Thu Dec 17 09:03:57 1998
@@ -63,6 +63,7 @@
 #include <asm/spinlock.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 
 #ifdef EL3_DEBUG
 int el3_debug = EL3_DEBUG;
@@ -407,7 +408,7 @@
 	/* Set the spinlock before grabbing IRQ! */
 	((struct el3_private *)dev->priv)->lock = (spinlock_t) SPIN_LOCK_UNLOCKED;
 
-	if (request_irq(dev->irq, &el3_interrupt, 0, "3c509", dev)) {
+	if (request_irq(dev->irq, &el3_interrupt, 0, dev->name, dev)) {
 		return -EAGAIN;
 	}
 
@@ -526,10 +527,21 @@
 	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
 		printk("%s: Transmitter access conflict.\n", dev->name);
 	else {
-		unsigned long flags;
-
-	    	/* Spin on the lock, until we're clear of an IRQ */
-	    	spin_lock_irqsave(&lp->lock, flags);
+		/*
+		 *	We lock the driver against other processors. Note
+		 *	we don't need to lock versus the IRQ as we suspended
+		 *	that. This means that we lose the ability to take
+		 *	an RX during a TX upload. That sucks a bit with SMP
+		 *	on an original 3c509 (2K buffer)
+		 *
+		 *	Using disable_irq stops us crapping on other
+		 *	time sensitive devices.
+		 */
+
+#ifdef __SMP__
+		disable_irq(dev->irq);
+	    	spin_lock(&lp->lock);
+#endif	    	
 	    
 		/* Put out the doubleword header... */
 		outw(skb->len, ioaddr + TX_FIFO);
@@ -547,8 +559,10 @@
 		} else
 			/* Interrupt us when the FIFO has room for max-sized packet. */
 			outw(SetTxThreshold + 1536, ioaddr + EL3_CMD);
-
-		spin_unlock_irqrestore(&lp->lock, flags);
+#ifdef __SMP__
+		spin_unlock(&lp->lock);
+		enable_irq(dev->irq);
+#endif		
 	}
 
 	dev_kfree_skb (skb);
@@ -658,10 +672,14 @@
 	struct el3_private *lp = (struct el3_private *)dev->priv;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	/*
+	 *	This is fast enough not to bother with disable IRQ
+	 *	stuff.
+	 */
+	 
+	spin_lock_irqsave(&lp->lock, flags);
 	update_stats(dev);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&lp->lock, flags);
 	return &lp->stats;
 }
 
@@ -683,13 +701,13 @@
 	EL3WINDOW(6);
 	lp->stats.tx_carrier_errors 	+= inb(ioaddr + 0);
 	lp->stats.tx_heartbeat_errors	+= inb(ioaddr + 1);
-	/* Multiple collisions. */	   	inb(ioaddr + 2);
-	lp->stats.collisions			+= inb(ioaddr + 3);
-	lp->stats.tx_window_errors		+= inb(ioaddr + 4);
-	lp->stats.rx_fifo_errors		+= inb(ioaddr + 5);
-	lp->stats.tx_packets			+= inb(ioaddr + 6);
-	/* Rx packets	*/				inb(ioaddr + 7);
-	/* Tx deferrals */				inb(ioaddr + 8);
+	/* Multiple collisions. */	   inb(ioaddr + 2);
+	lp->stats.collisions		+= inb(ioaddr + 3);
+	lp->stats.tx_window_errors	+= inb(ioaddr + 4);
+	lp->stats.rx_fifo_errors	+= inb(ioaddr + 5);
+	lp->stats.tx_packets		+= inb(ioaddr + 6);
+	/* Rx packets	*/		   inb(ioaddr + 7);
+	/* Tx deferrals */		   inb(ioaddr + 8);
 	inw(ioaddr + 10);	/* Total Rx and Tx octets. */
 	inw(ioaddr + 12);
 
diff -u --recursive --new-file v2.1.131/linux/drivers/net/3c515.c linux/drivers/net/3c515.c
--- v2.1.131/linux/drivers/net/3c515.c	Thu Nov 12 16:21:19 1998
+++ linux/drivers/net/3c515.c	Thu Dec 17 09:03:57 1998
@@ -39,16 +39,8 @@
 #define RX_RING_SIZE	16
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 #include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -67,12 +59,9 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#if (LINUX_VERSION_CODE >= 0x10344)
+
 #define NEW_MULTICAST
 #include <linux/delay.h>
-#else
-#define udelay(microsec)	do { int _i = 4*microsec; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
-#endif
 
 /* Kernel version compatibility functions. */
 #define RUN_AT(x) (jiffies + (x))
diff -u --recursive --new-file v2.1.131/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.1.131/linux/drivers/net/3c523.c	Thu Nov 12 16:21:19 1998
+++ linux/drivers/net/3c523.c	Thu Dec 17 09:03:57 1998
@@ -359,7 +359,7 @@
 	DELAY(2);
 
 	p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
-	p->scb = (struct scb_struct *) (dev->mem_start);
+	p->scb = (struct scb_struct *) phys_to_virt(dev->mem_start);
 	p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
 
 	memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
@@ -523,7 +523,7 @@
 	   Which we don't care much about here.  We'll just tell Linux that
 	   we're using 16K.  MCA won't permit adress space conflicts caused
 	   by not mapping the other 8K. */
-	dev->mem_start = phys_to_virt(shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3]);
+	dev->mem_start = shm_table[(status & ELMC_STATUS_MEMORY_SELECT) >> 3];
 
 	/* We're using MCA, so it's a given that the information about memory
 	   size is correct.  The Crynwr drivers do something like this. */
@@ -531,7 +531,7 @@
 	elmc_id_reset586();	/* seems like a good idea before checking it... */
 
 	size = 0x4000;		/* check for 16K mem */
-	if (!check586(dev, (char *) dev->mem_start, size)) {
+	if (!check586(dev, (char *) phys_to_virt(dev->mem_start), size)) {
 		printk("%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
 		       dev->mem_start);
 		release_region(dev->base_addr, ELMC_IO_EXTENT);
@@ -539,7 +539,7 @@
 	}
 	dev->mem_end = dev->mem_start + size;	/* set mem_end showed by 'ifconfig' */
 
-	((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000;
+	((struct priv *) (dev->priv))->base = phys_to_virt(dev->mem_start + size - 0x01000000);
 	alloc586(dev);
 
 	elmc_id_reset586();	/* make sure it doesn't generate spurious ints */
@@ -550,8 +550,7 @@
 	/* dump all the assorted information */
 	printk("%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
 	       dev->irq, dev->if_port ? "ex" : "in", 
-	       virt_to_phys(dev->mem_start), 
-	       virt_to_phys(dev->mem_end - 1));
+	       dev->mem_start, dev->mem_end - 1);
 
 	/* The hardware address for the 3c523 is stored in the first six
 	   bytes of the IO address. */
@@ -628,7 +627,7 @@
 
 	s = jiffies;		/* warning: only active with interrupts on !! */
 	while (!(cfg_cmd->cmd_status & STAT_COMPL)) {
-		if (jiffies - s > 30)
+		if (jiffies - s > 30*HZ/100)
 			break;
 	}
 
@@ -654,7 +653,7 @@
 
 	s = jiffies;
 	while (!(ias_cmd->cmd_status & STAT_COMPL)) {
-		if (jiffies - s > 30)
+		if (jiffies - s > 30*HZ/100)
 			break;
 	}
 
@@ -679,7 +678,7 @@
 
 	s = jiffies;
 	while (!(tdr_cmd->cmd_status & STAT_COMPL)) {
-		if (jiffies - s > 30) {
+		if (jiffies - s > 30*HZ/100) {
 			printk("%s: %d Problems while running the TDR.\n", dev->name, __LINE__);
 			result = 1;
 			break;
@@ -768,7 +767,7 @@
 			elmc_id_attn586();
 			s = jiffies;
 			while (!(mc_cmd->cmd_status & STAT_COMPL)) {
-				if (jiffies - s > 30)
+				if (jiffies - s > 30*HZ/100)
 					break;
 			}
 			if (!(mc_cmd->cmd_status & STAT_COMPL)) {
diff -u --recursive --new-file v2.1.131/linux/drivers/net/Makefile linux/drivers/net/Makefile
--- v2.1.131/linux/drivers/net/Makefile	Fri Nov 27 13:09:23 1998
+++ linux/drivers/net/Makefile	Fri Dec 18 09:37:50 1998
@@ -5,7 +5,7 @@
 
 SUB_DIRS     := 
 MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS) hamradio
+ALL_SUB_DIRS := $(SUB_DIRS) hamradio irda
 
 L_TARGET := net.a
 L_OBJS   := auto_irq.o
@@ -384,6 +384,10 @@
 
 ifeq ($(CONFIG_LANCE),y)
 L_OBJS += lance.o
+else
+  ifeq ($(CONFIG_LANCE),m)
+  M_OBJS += lance.o
+  endif
 endif
 
 ifeq ($(CONFIG_PCNET32),y)
@@ -752,6 +756,16 @@
   endif
 endif
 
+ifeq ($(CONFIG_COSA),y)
+L_OBJS += cosa.o
+CONFIG_SYNCPPP_BUILTIN = y
+else
+  ifeq ($(CONFIG_COSA),m)
+  CONFIG_SYNCPPP_MODULE = y
+  M_OBJS += cosa.o
+  endif
+endif
+
 # If anything built-in uses syncppp, then build it into the kernel also.
 # If not, but a module uses it, build as a module.
 
@@ -965,6 +979,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_RCPCI),y)
+L_OBJS += rcpci.o
+else
+  ifeq ($(CONFIG_RCPCI),m)
+  M_OBJS += rcpci.o
+  endif
+endif
+
 ifeq ($(CONFIG_MACE),y)
 L_OBJS += mace.o
 endif
@@ -1029,6 +1051,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_IRDA),y)
+SUB_DIRS += irda
+else
+  ifeq ($(CONFIG_IRDA),m)
+  MOD_SUB_DIRS += irda
+  endif
+endif
+
 include $(TOPDIR)/Rules.make
 
 clean:
@@ -1036,3 +1066,6 @@
 
 wanpipe.o: $(WANPIPE_OBJS)
 	ld -r -o $@ $(WANPIPE_OBJS)
+
+rcpci.o: rcpci45.o rcmtl.o
+	$(LD) -r -o rcpci.o rcpci45.o rcmtl.o
diff -u --recursive --new-file v2.1.131/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.1.131/linux/drivers/net/Space.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/net/Space.c	Fri Dec 18 09:37:40 1998
@@ -111,6 +111,8 @@
 extern int hplance_probe(struct device *dev);
 extern int via_rhine_probe(struct device *dev);
 extern int tc515_probe(struct device *dev);
+extern int lance_probe(struct device *dev);
+extern int rcpci_probe(struct device *);
 
 /* Gigabit Ethernet adapters */
 extern int yellowfin_probe(struct device *dev);
@@ -169,6 +171,9 @@
 #ifdef CONFIG_DGRS
 	{dgrs_probe, 0},
 #endif
+#ifdef CONFIG_RCPCI
+	{rcpci_probe, 0},
+#endif
 #ifdef CONFIG_VORTEX
 	{tc59x_probe, 0},
 #endif
@@ -297,6 +302,9 @@
 #ifdef CONFIG_NE2000		/* ISA (use ne2k-pci for PCI cards) */
 	{ne_probe, 0},
 #endif
+#ifdef CONFIG_LANCE		/* ISA/VLB (use pcnet32 for PCI cards) */
+	{lance_probe, 0},
+#endif
 #ifdef CONFIG_SMC9194
 	{smc_init, 0},
 #endif
@@ -709,6 +717,9 @@
 #endif
 #ifdef CONFIG_SKTR
 	&& sktr_probe(dev)
+#endif
+#ifdef CONFIG_SMCTR
+	&& smctr_probe(dev)
 #endif
 	&& 1 ) {
 	return 1;	/* -ENODEV or -EAGAIN would be more accurate. */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v2.1.131/linux/drivers/net/ac3200.c	Fri Oct  9 13:27:08 1998
+++ linux/drivers/net/ac3200.c	Thu Dec 17 09:03:57 1998
@@ -407,7 +407,6 @@
 			release_region(dev->base_addr, AC_IO_EXTENT);
 			if (ei_status.reg0)
 				iounmap((void *)dev->mem_start);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.1.131/linux/drivers/net/acenic.c	Fri Nov 27 13:09:23 1998
+++ linux/drivers/net/acenic.c	Sun Dec 20 04:36:47 1998
@@ -13,8 +13,6 @@
  * (at your option) any later version.
  */
 
-#define DEBUG 1
-#define RX_DMA_SKBUFF 1
 #define PKT_COPY_THRESHOLD 300
 
 #include <linux/module.h>
@@ -70,14 +68,71 @@
  * by running `ifconfig eth<X> mtu <MTU>' with <X> being the Ethernet
  * interface number and <MTU> being the MTU value.
  *
+ * Module parameters:
+ *
+ * When compiled as a loadable module, the driver allows for a number
+ * of module parameters to be specified. The driver supports the
+ * following module parameters:
+ *
+ *  trace=<val> - Firmware trace level. This requires special traced
+ *                firmware to replace the firmware supplied with
+ *                the driver - for debugging purposes only.
+ *
+ *  link=<val>  - Link state. Normally you want to use the default link
+ *                parameters set by the driver. This can be used to
+ *                override these in case your switch doesn't negotiate
+ *                the link properly. Valid values are:
+ *         0x0001 - Force half duplex link.
+ *         0x0002 - Do not negotiate line speed with the other end.
+ *         0x0010 - 10Mbit/sec link.
+ *         0x0020 - 100Mbit/sec link.
+ *         0x0040 - 1000Mbit/sec link.
+ *         0x0100 - Do not negotiate flow control.
+ *         0x0200 - Enable RX flow control Y
+ *         0x0400 - Enable TX flow control Y (Tigon II NICs only).
+ *                Default value is 0x0270, ie. enable link+flow
+ *                control negotiation. Negotiating the highest
+ *                possible link speed with RX flow control enabled.
+ *
+ *                When disabling link speed negotiation, only one link
+ *                speed is allowed to be specified!
+ *
+ *  tx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
+ *                to wait for more packets to arive before
+ *                interrupting the host, from the time the first
+ *                packet arrives.
+ *
+ *  rx_coal_tick=<val> - number of coalescing clock ticks (us) allowed
+ *                to wait for more packets to arive in the transmit ring,
+ *                before interrupting the host, after transmitting the
+ *                first packet in the ring.
+ *
+ *  max_tx_desc=<val> - maximum number of transmit descriptors
+ *                (packets) transmitted before interrupting the host.
+ *
+ *  max_rx_desc=<val> - maximum number of receive descriptors
+ *                (packets) received before interrupting the host.
+ *
+ * If you use more than one NIC, specify the parameters for the
+ * individual NICs with a comma, ie. trace=0,0x00001fff,0 you want to
+ * run tracing on NIC #2 but not on NIC #1 and #3.
+ *
  * TODO:
  *
  * - Add multicast support.
- * - Make all the tuning parameters and link speed negotiation, user
- *   settable at driver/module init time.
+ * - The Tigon II firmware fails to run in some PCs.
+ * - NIC dump support.
+ * - More tuning parameters.
  */
 
-static const char *version = "acenic.c: v0.13 11/25/98  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static int link[8] = {0, };
+static int trace[8] = {0, };
+static int tx_coal_tick[8] = {0, };
+static int rx_coal_tick[8] = {0, };
+static int max_tx_desc[8] = {0, };
+static int max_rx_desc[8] = {0, };
+
+static const char *version = "acenic.c: v0.19 12/17/98  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
 
 static struct device *root_dev = NULL;
 
@@ -149,6 +204,7 @@
 
 		if (!(ap->pci_command & PCI_COMMAND_MASTER)){
 			ap->pci_command |= PCI_COMMAND_MASTER;
+
 			pcibios_write_config_word(pci_bus, pci_dev_fun,
 						  PCI_COMMAND,
 						  ap->pci_command);
@@ -226,7 +282,11 @@
 			break;
 		}
 
-		ace_init(dev);
+#ifdef MODULE
+		ace_init(dev, boards_found);
+#else
+		ace_init(dev, -1);
+#endif
 
 		boards_found++;
 
@@ -255,6 +315,17 @@
 
 
 #ifdef MODULE
+#if LINUX_VERSION_CODE > 0x20118
+MODULE_AUTHOR("Jes Sorensen <Jes.Sorensen@cern.ch>");
+MODULE_DESCRIPTION("AceNIC/3C985 Gigabit Ethernet driver");
+MODULE_PARM(link, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(trace, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(tx_coal_tick, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_tx_desc, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(rx_coal_tick, "1-" __MODULE_STRING(8) "i");
+MODULE_PARM(max_rx_desc, "1-" __MODULE_STRING(8) "i");
+#endif
+
 int init_module(void)
 {
 	int cards;
@@ -299,6 +370,8 @@
 		}
 
 		iounmap(regs);
+		if(ap->trace_buf)
+			kfree(ap->trace_buf);
 		kfree(ap->info);
 		free_irq(root_dev->irq, root_dev);
 		unregister_netdev(root_dev);
@@ -326,7 +399,7 @@
 }
 
 
-__initfunc(static int ace_init(struct device *dev))
+__initfunc(static int ace_init(struct device *dev, int board_idx))
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -345,7 +418,7 @@
 
 	{
 		long myjif = jiffies + HZ;
-		while (myjif > jiffies);
+		while (time_before(jiffies, myjif));
 	}
 #endif
 
@@ -430,7 +503,14 @@
 	 */
 	tmp = READ_CMD_MEM | WRITE_CMD_MEM;
 	if (ap->version == 2){
+#if 0
+		/*
+		 * According to the documentation this enables writes
+		 * to all PCI regs - NOT good.
+		 */
 		tmp |= DMA_WRITE_ALL_ALIGN;
+#endif
+		tmp |= MEM_READ_MULTIPLE;
 		if (ap->pci_command & PCI_COMMAND_INVALIDATE){
 			switch(L1_CACHE_BYTES){
 			case 16:
@@ -473,6 +553,13 @@
 		return -EAGAIN;
 	}
 
+	/*
+	 * Register the device here to be able to catch allocated
+	 * interrupt handlers in case the firmware doesn't come up.
+	 */
+	ap->next = root_dev;
+	root_dev = dev;
+
 	ap->info = info;
 	memset(info, 0, sizeof(struct ace_info));
 
@@ -546,12 +633,16 @@
 
 	info->tx_csm_ptr = virt_to_bus(&ap->tx_csm);
 
+	/*
+	 * Potential item for tuning parameter
+	 */
 	regs->DmaReadCfg = DMA_THRESH_8W;
 	regs->DmaWriteCfg = DMA_THRESH_8W;
 
 	regs->MaskInt = 0;
 	regs->IfIdx = 1;
 
+	regs->AssistState = 1;
 #if 0
 {
 	u32 tmp;
@@ -565,22 +656,87 @@
 	regs->MacRxState = tmp;
 }
 #endif
+
 	regs->TuneStatTicks = 2 * TICKS_PER_SEC;
-	regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
-	regs->TuneMaxTxDesc = 7;
-	regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
-	regs->TuneMaxRxDesc = 2;
-	regs->TuneTrace = 0 /* 0x30001fff */;
-	tmp = LNK_ENABLE | LNK_FULL_DUPLEX | LNK_1000MB |
-		LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE;
-	if(ap->version == 1)
-		regs->TuneLink = tmp;
-	else{
-		tmp |= LNK_TX_FLOW_CTL_Y;
-		regs->TuneLink = tmp;
-		regs->TuneFastLink = tmp;
+
+	if ((board_idx < 8) && tx_coal_tick[board_idx])
+		regs->TuneTxCoalTicks = tx_coal_tick[board_idx] *
+			TICKS_PER_SEC / 1000;
+	else
+		regs->TuneTxCoalTicks = TICKS_PER_SEC / 500;
+	if ((board_idx < 8) && max_tx_desc[board_idx])
+		regs->TuneMaxTxDesc = max_tx_desc[board_idx];
+	else
+		regs->TuneMaxTxDesc = 7;
+
+	if ((board_idx < 8) && rx_coal_tick[board_idx])
+		regs->TuneRxCoalTicks = rx_coal_tick[board_idx] *
+			TICKS_PER_SEC / 1000;
+	else
+		regs->TuneRxCoalTicks = TICKS_PER_SEC / 10000;
+	if ((board_idx < 8) && max_rx_desc[board_idx])
+		regs->TuneMaxRxDesc = max_rx_desc[board_idx];
+	else
+		regs->TuneMaxRxDesc = 2;
+
+	if (board_idx < 8)
+		regs->TuneTrace = trace[board_idx];
+	else
+		regs->TuneTrace = 0;
+
+	tmp = LNK_ENABLE;
+
+	if ((board_idx > 7) || !(link[board_idx])){
+		if (board_idx > 8)
+			printk(KERN_WARNING "%s: more then 8 NICs detected, "
+			       "ignoring link options!\n", dev->name);
+		/*
+		 * No link options specified, we go for the defaults
+		 */
+		tmp |=  LNK_FULL_DUPLEX | LNK_1000MB | LNK_100MB | LNK_10MB |
+			LNK_RX_FLOW_CTL_Y | LNK_NEG_FCTL | LNK_NEGOTIATE;
+
+		if(ap->version == 2)
+			tmp |= LNK_TX_FLOW_CTL_Y;
+	} else {
+		int option = link[board_idx];
+		if (option & 0x01){
+			printk(KERN_INFO "%s: Setting half duplex link\n",
+			       dev->name);
+			tmp |= LNK_FULL_DUPLEX;
+		}
+		if ((option & 0x02) == 0)
+			tmp |= LNK_NEGOTIATE;
+		if (option & 0x10)
+			tmp |= LNK_10MB;
+		if (option & 0x20)
+			tmp |= LNK_100MB;
+		if (option & 0x40)
+			tmp |= LNK_1000MB;
+		if ((option & 0x70) == 0){
+			printk(KERN_WARNING "%s: No media speed specified, "
+			       "forcing auto negotiation\n", dev->name);
+			tmp |= LNK_NEGOTIATE | LNK_1000MB |
+				LNK_100MB | LNK_10MB;
+		}
+		if ((option & 0x100) == 0)
+			tmp |= LNK_NEG_FCTL;
+		else
+			printk(KERN_INFO "%s: Disabling flow control "
+			       "negotiation\n", dev->name);
+		if (option & 0x200)
+			tmp |= LNK_RX_FLOW_CTL_Y;
+		if ((option & 0x400) && (ap->version == 2)){
+			printk(KERN_INFO "%s: Enabling TX flow control\n",
+			       dev->name);
+			tmp |= LNK_TX_FLOW_CTL_Y;
+		}
 	}
 
+	regs->TuneLink = tmp;
+	if (ap->version == 2)
+		regs->TuneFastLink = tmp;
+
 	if (ap->version == 1)
 		regs->Pc = tigonFwStartAddr;
 	else if (ap->version == 2)
@@ -595,18 +751,17 @@
 	regs->CpuCtrl = (regs->CpuCtrl & ~(CPU_HALT | CPU_TRACE));
 
 	/*
-	 * Wait for the firmware to spin up - max 2 seconds.
+	 * Wait for the firmware to spin up - max 3 seconds.
 	 */
 	myjif = jiffies + 3 * HZ;
-	while ((myjif > jiffies) && !ap->fw_running);
+	while (time_before(jiffies, myjif) && !ap->fw_running);
 	if (!ap->fw_running){
 		printk(KERN_ERR "%s: firmware NOT running!\n", dev->name);
+		ace_dump_trace(ap);
+		regs->CpuCtrl |= CPU_HALT;
 		return -EBUSY;
 	}
 
-	ap->next = root_dev;
-	root_dev = dev;
-
 	/*
 	 * We load the ring here as there seem to be no way to tell the
 	 * firmware to wipe the ring without re-initializing it.
@@ -620,7 +775,6 @@
 /*
  * Monitor the card to detect hangs.
  */
-
 static void ace_timer(unsigned long data)
 {
 	struct device *dev = (struct device *)data;
@@ -643,6 +797,17 @@
 
 
 /*
+ * Copy the contents of the NIC's trace buffer to kernel memory.
+ */
+static void ace_dump_trace(struct ace_private *ap)
+{
+	if (!ap->trace_buf)
+		if (!(ap->trace_buf = kmalloc(ACE_TRACE_SIZE, GFP_KERNEL)));
+		    return;
+}
+
+
+/*
  * Load the standard rx ring.
  */
 static int ace_load_std_rx_ring(struct device *dev)
@@ -822,7 +987,6 @@
 			ap->fw_running = 1;
 			break;
 		case E_STATS_UPDATED:
-			mod_timer(&ap->timer, jiffies + (5/2*HZ));
 			break;
 		case E_LNK_STATE:
 		{
@@ -1036,18 +1200,6 @@
 		return;
 	}
 
-#if 0
-	/*
-	 * Since we are also using a spinlock, I wonder if this is
-	 * actually worth it.
-	 */
-	if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) {
-		printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n",
-		       dev->name);
-		return;
-	}
-#endif
-
 	/*
 	 * Tell the card not to generate interrupts while we are in here.
 	 */
@@ -1076,6 +1228,12 @@
 			ap->tx_full = 0;
 			dev->tbusy = 0;
 			mark_bh(NET_BH);
+
+			/*
+			 * TX ring is no longer full, aka the
+			 * transmitter is working fine - kill timer.
+			 */
+			del_timer(&ap->timer);
 		}
 
 		ap->tx_ret_csm = txcsm;
@@ -1098,9 +1256,6 @@
 	regs->Mb0Lo = 0;
 
 	spin_unlock(&ap->lock);
-#if 0
-	dev->interrupt = 0;
-#endif
 }
 
 
@@ -1140,7 +1295,7 @@
 
 #if 0
 	{ long myjif = jiffies + HZ;
-	while (jiffies < myjif);
+	while (time_before(jiffies, myjif));
 	}
 
 	cmd.evt = C_LNK_NEGOTIATION;
@@ -1159,10 +1314,8 @@
 	 * Setup the timer
 	 */
 	init_timer(&ap->timer);
-	ap->timer.expires = jiffies + 5/2 * HZ;
 	ap->timer.data = (unsigned long)dev;
-	ap->timer.function = &ace_timer;
-	add_timer(&ap->timer);
+	ap->timer.function = ace_timer;
 	return 0;
 }
 
@@ -1239,6 +1392,12 @@
 	if ((idx + 1) % TX_RING_ENTRIES == ap->tx_ret_csm){
 		ap->tx_full = 1;
 		set_bit(0, (void*)&dev->tbusy);
+		/*
+		 * Queue is full, add timer to detect whether the
+		 * transmitter is stuck.
+		 */
+		ap->timer.expires = jiffies + (3 * HZ);
+		add_timer(&ap->timer);
 	}
 
 	spin_unlock_irqrestore(&ap->lock, flags);
diff -u --recursive --new-file v2.1.131/linux/drivers/net/acenic.h linux/drivers/net/acenic.h
--- v2.1.131/linux/drivers/net/acenic.h	Fri Nov 27 13:09:23 1998
+++ linux/drivers/net/acenic.h	Thu Dec 17 09:03:57 1998
@@ -142,6 +142,8 @@
 #define ACE_JUMBO_MTU 9000
 #define ACE_STD_MTU 1500
 
+#define ACE_TRACE_SIZE 0x8000
+
 /*
  * Host control register bits.
  */
@@ -205,20 +207,13 @@
 #define DMA_WRITE_MAX_128	0xa0
 #define DMA_WRITE_MAX_256	0xc0
 #define DMA_WRITE_MAX_1K	0xe0
+#define MEM_READ_MULTIPLE	0x00020000
 #define DMA_WRITE_ALL_ALIGN	0x00800000
 #define READ_CMD_MEM		0x06000000
 #define WRITE_CMD_MEM		0x70000000
 
 
 /*
- * Transmit status.
- */
-
-#define ENA_XMIT		0x01
-#define PERM_CON		0x02
-
-
-/*
  * Mode status
  */
 
@@ -580,9 +575,11 @@
 				__attribute__ ((aligned (L1_CACHE_BYTES)));
 	struct device		*next
 				__attribute__ ((aligned (L1_CACHE_BYTES)));
+	unsigned char		*trace_buf;
 	int			fw_running, fw_up, jumbo, promisc;
 	int			version;
-	int			vendor;
+	int			flags;
+	u16			vendor;
 	u16			pci_command;
 	u8			pci_bus;
 	u8			pci_dev_fun;
@@ -593,7 +590,7 @@
 /*
  * Prototypes
  */
-static int ace_init(struct device *dev);
+static int ace_init(struct device *dev, int board_idx);
 static int ace_load_std_rx_ring(struct device *dev);
 static int ace_load_jumbo_rx_ring(struct device *dev);
 static int ace_flush_jumbo_rx_ring(struct device *dev);
@@ -603,6 +600,7 @@
 static int ace_start_xmit(struct sk_buff *skb, struct device *dev);
 static int ace_close(struct device *dev);
 static void ace_timer(unsigned long data);
+static void ace_dump_trace(struct ace_private *ap);
 static void ace_set_multicast_list(struct device *dev);
 static int ace_change_mtu(struct device *dev, int new_mtu);
 static int ace_set_mac_addr(struct device *dev, void *p);
diff -u --recursive --new-file v2.1.131/linux/drivers/net/acenic_firmware.h linux/drivers/net/acenic_firmware.h
--- v2.1.131/linux/drivers/net/acenic_firmware.h	Fri Nov 27 13:09:23 1998
+++ linux/drivers/net/acenic_firmware.h	Thu Dec 17 09:03:57 1998
@@ -1,28 +1,28 @@
 /* Generated by genfw.c */
 int tigonFwReleaseMajor = 0xc;
 int tigonFwReleaseMinor = 0x1;
-int tigonFwReleaseFix = 0x4;
+int tigonFwReleaseFix = 0x6;
 u32 tigonFwStartAddr = 0x4000;
 u32 tigonFwTextAddr = 0x4000;
-int tigonFwTextLen = 0x10300;
-u32 tigonFwDataAddr = 0x14d40;
+int tigonFwTextLen = 0x10500;
+u32 tigonFwDataAddr = 0x14f50;
 int tigonFwDataLen = 0x140;
-u32 tigonFwRodataAddr = 0x14300;
-int tigonFwRodataLen = 0xa20;
-u32 tigonFwBssAddr = 0x14eb0;
+u32 tigonFwRodataAddr = 0x14500;
+int tigonFwRodataLen = 0xa30;
+u32 tigonFwBssAddr = 0x150c0;
 int tigonFwBssLen = 0x2080;
-u32 tigonFwSbssAddr = 0x14e80;
+u32 tigonFwSbssAddr = 0x15090;
 int tigonFwSbssLen = 0x28;
-u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] = {
-0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd4d74, 
+u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __init = {
+0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 0x8fbd4f84, 
 0x3a0f021, 0x3c100000, 0x26104000, 0xc00100c, 0x0, 0xd, 
 0x27bdffd8, 0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021, 0x3c170013, 
-0x36f75430, 0x2e02021, 0x340583d0, 0xafbf0024, 0xc00242c, 0xafb00020, 
-0xc00238c, 0x0, 0x3c040001, 0x24844360, 0x24050001, 0x2e03021, 
-0x3821, 0x3c100001, 0x26106f30, 0xafb00010, 0xc0023a7, 0xafbb0014, 
+0x36f75430, 0x2e02021, 0x340583d0, 0xafbf0024, 0xc002488, 0xafb00020, 
+0xc0023e8, 0x0, 0x3c040001, 0x24844560, 0x24050001, 0x2e03021, 
+0x3821, 0x3c100001, 0x26107140, 0xafb00010, 0xc002403, 0xafbb0014, 
 0x3c02000f, 0x3442ffff, 0x2021024, 0x362102b, 0x10400009, 0x24050003, 
-0x3c040001, 0x2484436c, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010, 
-0xc0023a7, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821, 
+0x3c040001, 0x2484456c, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010, 
+0xc002403, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821, 
 0xa02083a0, 0x3c010001, 0x370821, 0xa02083a2, 0x3c010001, 0x370821, 
 0xa02083a3, 0x3c010001, 0x370821, 0xac2083a4, 0xa2e004c8, 0x418c0, 
 0x24840001, 0x771021, 0xac40726c, 0x771021, 0xac407270, 0x2e31021, 
@@ -46,122 +46,124 @@
 0x8f8200b0, 0x8ee304bc, 0x431025, 0xaf8200b0, 0x8f8200b0, 0x30420004, 
 0x1440fffd, 0x0, 0x8ee20450, 0x8ee30454, 0xaee304ec, 0x8ee204ec, 
 0x2442e000, 0x2c422001, 0x1440000d, 0x26e40030, 0x8ee20450, 0x8ee30454, 
-0x3c040001, 0x24844378, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704ec, 
-0x34a5f000, 0xc0023a7, 0x603021, 0x26e40030, 0xc00242c, 0x24050400, 
-0x27440080, 0xc00242c, 0x24050080, 0x26e4776c, 0xc00242c, 0x24050400, 
+0x3c040001, 0x24844578, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704ec, 
+0x34a5f000, 0xc002403, 0x603021, 0x26e40030, 0xc002488, 0x24050400, 
+0x27440080, 0xc002488, 0x24050080, 0x26e4776c, 0xc002488, 0x24050400, 
 0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260, 0x27450200, 0x24060008, 
-0xaee20068, 0x24020006, 0xc00243e, 0xaee20064, 0x3c023b9a, 0x3442ca00, 
+0xaee20068, 0x24020006, 0xc00249a, 0xaee20064, 0x3c023b9a, 0x3442ca00, 
 0x2021, 0x24030002, 0xaee30074, 0xaee30070, 0xaee2006c, 0x240203e8, 
 0xaee20104, 0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001, 0x641821, 
-0x90634d40, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 
+0x90634f50, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 
 0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 
 0xa062009c, 0x2e41021, 0xa040009c, 0x96e2046a, 0x30420003, 0x14400009, 
-0x0, 0x96e2047a, 0x30420003, 0x5040012b, 0x3c030800, 0x96e2046a, 
+0x0, 0x96e2047a, 0x30420003, 0x50400131, 0x3c030800, 0x96e2046a, 
 0x30420003, 0x1040002a, 0x3c020700, 0x96e2047a, 0x30420003, 0x10400026, 
 0x3c020700, 0x96e3047a, 0x96e2046a, 0x14620022, 0x3c020700, 0x8ee204b0, 
 0x24030001, 0xa2e34e10, 0x34420e00, 0xaee204b0, 0x8f420218, 0x30420100, 
-0x10400005, 0x0, 0x3c020001, 0x2442ded0, 0x800111d, 0x21100, 
-0x3c020001, 0x2442d0d0, 0x21100, 0x21182, 0x3c030800, 0x431025, 
-0x3c010001, 0xac220f38, 0x3c020001, 0x2442f3c8, 0x21100, 0x21182, 
-0x3c030800, 0x431025, 0x3c010001, 0xac220f78, 0x8ee20000, 0x34424000, 
-0x8001232, 0xaee20000, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, 
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, 
+0x10400005, 0x0, 0x3c020001, 0x2442e128, 0x800111d, 0x21100, 
+0x3c020001, 0x2442d31c, 0x21100, 0x21182, 0x3c030800, 0x431025, 
+0x3c010001, 0xac221138, 0x3c020001, 0x2442f640, 0x21100, 0x21182, 
+0x3c030800, 0x431025, 0x3c010001, 0xac221178, 0x8ee20000, 0x34424000, 
+0x8001238, 0xaee20000, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, 
+0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0, 
 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 
 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
-0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0, 
-0x800119d, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001187, 
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800119d, 
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 
-0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800121d, 0x0, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, 
-0xaee201a0, 0x8001201, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, 
+0x3021, 0x24420001, 0xaee201a0, 0x80011a0, 0x8ee201a0, 0x8ee405f8, 
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008, 
+0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc, 
+0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 
+0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 
+0x10a20005, 0x0, 0x800118a, 0x0, 0x14a00005, 0x0, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
+0x50400013, 0xac800000, 0x80011a0, 0x0, 0x8ee24e20, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 
+0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584, 
+0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 
+0x34a5f000, 0x8001223, 0x0, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, 
+0xaee201a0, 0x8001207, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 
 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 
 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10a20005, 0x0, 0x80011eb, 0x0, 0x14a00005, 
+0x24420001, 0x10a20005, 0x0, 0x80011f1, 0x0, 0x14a00005, 
 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400013, 0xac800000, 0x8001201, 0x0, 0x8ee24e20, 
+0x2c420011, 0x50400013, 0xac800000, 0x8001207, 0x0, 0x8ee24e20, 
 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 
 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 
 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001, 
-0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800121d, 
-0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228, 
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
-0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248443a4, 0x3405f001, 0x24420001, 
-0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc0023a7, 
-0xafa00014, 0x8001232, 0x0, 0x3c020001, 0x2442f2f0, 0x21100, 
-0x21182, 0x431025, 0x3c010001, 0xac220f78, 0x96e2045a, 0x30420003, 
+0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
+0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001223, 
+0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228, 
+0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
+0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248445a4, 0x3405f001, 0x24420001, 
+0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc002403, 
+0xafa00014, 0x8001238, 0x0, 0x3c020001, 0x2442f568, 0x21100, 
+0x21182, 0x431025, 0x3c010001, 0xac221178, 0x96e2045a, 0x30420003, 
 0x10400025, 0x3c050fff, 0x8ee204b8, 0x34a5ffff, 0x34420a00, 0xaee204b8, 
-0x8ee304b8, 0x3c040001, 0x248443b0, 0x24020001, 0xa2e204dc, 0xa2e204dd, 
-0x3c020002, 0x621825, 0x3c020001, 0x2442a1c0, 0x451024, 0x21082, 
-0xaee304b8, 0x3c030800, 0x431025, 0x3c010001, 0xac220f20, 0x3c020001, 
-0x2442abb4, 0x451024, 0x21082, 0x431025, 0x3c010001, 0xac220f80, 
-0x96e6045a, 0x3821, 0x24050011, 0xafa00010, 0xc0023a7, 0xafa00014, 
-0x8001262, 0x0, 0x3c020001, 0x2442a7e0, 0x21100, 0x21182, 
-0x3c030800, 0x431025, 0x3c010001, 0xac220f80, 0x96e2046a, 0x30420010, 
-0x14400009, 0x0, 0x96e2047a, 0x30420010, 0x1040010c, 0x0, 
+0x8ee304b8, 0x3c040001, 0x248445b0, 0x24020001, 0xa2e204dc, 0xa2e204dd, 
+0x3c020002, 0x621825, 0x3c020001, 0x2442a390, 0x451024, 0x21082, 
+0xaee304b8, 0x3c030800, 0x431025, 0x3c010001, 0xac221120, 0x3c020001, 
+0x2442adb4, 0x451024, 0x21082, 0x431025, 0x3c010001, 0xac221180, 
+0x96e6045a, 0x3821, 0x24050011, 0xafa00010, 0xc002403, 0xafa00014, 
+0x8001268, 0x0, 0x3c020001, 0x2442a9d4, 0x21100, 0x21182, 
+0x3c030800, 0x431025, 0x3c010001, 0xac221180, 0x96e2046a, 0x30420010, 
+0x14400009, 0x0, 0x96e2047a, 0x30420010, 0x10400112, 0x0, 
 0x96e2046a, 0x30420010, 0x10400005, 0x3c020700, 0x96e2047a, 0x30420010, 
-0x144000fc, 0x3c020700, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, 
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, 
+0x14400102, 0x3c020700, 0x34423000, 0xafa20018, 0x8ee205f8, 0x8f430228, 
+0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0, 
 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 
 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
-0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0, 
-0x80012e1, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80012cb, 
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80012e1, 
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 
-0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x8001361, 0x0, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, 
-0xaee201a0, 0x8001345, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, 
+0x3021, 0x24420001, 0xaee201a0, 0x80012ea, 0x8ee201a0, 0x8ee405f8, 
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008, 
+0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc, 
+0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 
+0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 
+0x10a20005, 0x0, 0x80012d4, 0x0, 0x14a00005, 0x0, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
+0x50400013, 0xac800000, 0x80012ea, 0x0, 0x8ee24e20, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 
+0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584, 
+0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 
+0x34a5f000, 0x800136d, 0x0, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, 
+0xaee201a0, 0x8001351, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 
 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 
 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10a20005, 0x0, 0x800132f, 0x0, 0x14a00005, 
+0x24420001, 0x10a20005, 0x0, 0x800133b, 0x0, 0x14a00005, 
 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400013, 0xac800000, 0x8001345, 0x0, 0x8ee24e20, 
+0x2c420011, 0x50400013, 0xac800000, 0x8001351, 0x0, 0x8ee24e20, 
 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 
 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 
 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001, 
-0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001361, 
-0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228, 
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
-0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248443a4, 0x3405f002, 0x24420001, 
-0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc0023a7, 
-0xafa00014, 0x96e6047a, 0x96e7046a, 0x3c040001, 0x248443bc, 0x24050012, 
-0xafa00010, 0xc0023a7, 0xafa00014, 0xc004440, 0x0, 0xc0022b8, 
+0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
+0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800136d, 
+0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228, 
+0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
+0x8ee201a8, 0x8ee2015c, 0x3c040001, 0x248445a4, 0x3405f002, 0x24420001, 
+0xaee2015c, 0x8ee2015c, 0x3021, 0x3821, 0xafa00010, 0xc002403, 
+0xafa00014, 0x96e6047a, 0x96e7046a, 0x3c040001, 0x248445bc, 0x24050012, 
+0xafa00010, 0xc002403, 0xafa00014, 0xc0044c0, 0x0, 0xc002314, 
 0x0, 0x3c060001, 0x34c63800, 0xaee005f8, 0xaf400228, 0xaf40022c, 
 0x96e30458, 0x8ee40000, 0x3c0512d8, 0x34a5c358, 0x27623800, 0xaee27248, 
 0x27623800, 0xaee27250, 0x27623800, 0xaee27254, 0x3661021, 0xaee27260, 
@@ -170,464 +172,391 @@
 0xaee05234, 0xaee05230, 0xaee0522c, 0xaee07240, 0xaee07244, 0xaee0724c, 
 0xaee07258, 0xaee004c0, 0x2463ffff, 0x852025, 0xaee304e8, 0xaee40000, 
 0xaf800060, 0xaf820064, 0x3c020100, 0xafa20018, 0x8ee205f8, 0x8f430228, 
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, 
+0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 0x210c0, 
 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 
 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
-0x15020007, 0x1021, 0x8ee201a0, 0x3021, 0x24420001, 0xaee201a0, 
-0x8001413, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80013fd, 
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8001413, 
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 
-0xaee905f8, 0x3c040001, 0x24844384, 0xafa00010, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x8001493, 0x0, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, 
-0xaee201a0, 0x8001477, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, 
+0x3021, 0x24420001, 0xaee201a0, 0x8001422, 0x8ee201a0, 0x8ee405f8, 
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 0x24020008, 
+0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 0x246305fc, 
+0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 
+0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 
+0x10a20005, 0x0, 0x800140c, 0x0, 0x14a00005, 0x0, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
+0x50400013, 0xac800000, 0x8001422, 0x0, 0x8ee24e20, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 
+0x24020001, 0xac820004, 0x54c0000c, 0xaee905f8, 0x3c040001, 0x24844584, 
+0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 
+0x34a5f000, 0x80014a5, 0x0, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3021, 0x24420001, 
+0xaee201a0, 0x8001489, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
 0x92e24e10, 0x14400037, 0x24060001, 0x8ee24e20, 0x210c0, 0x24425028, 
 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 
 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10a20005, 0x0, 0x8001461, 0x0, 0x14a00005, 
+0x24420001, 0x10a20005, 0x0, 0x8001473, 0x0, 0x14a00005, 
 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400013, 0xac800000, 0x8001477, 0x0, 0x8ee24e20, 
+0x2c420011, 0x50400013, 0xac800000, 0x8001489, 0x0, 0x8ee24e20, 
 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 
 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 
 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, 0x3c040001, 
-0x2484438c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8001493, 
-0x8ee201ac, 0x3c040001, 0x24844398, 0xafa00014, 0x8ee605f8, 0x8f470228, 
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
-0x8ee201a8, 0x8ee20150, 0x24420001, 0xaee20150, 0xc0014c8, 0x8ee20150, 
+0x2484458c, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
+0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x80014a5, 
+0x8ee201ac, 0x3c040001, 0x24844598, 0xafa00014, 0x8ee605f8, 0x8f470228, 
+0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
+0x8ee201a8, 0x8ee20150, 0x24420001, 0xaee20150, 0xc0014dc, 0x8ee20150, 
 0x8f8200a0, 0x30420004, 0x1440fffd, 0x0, 0x8f820040, 0x30420001, 
 0x14400008, 0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, 
 0x8f420264, 0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, 
-0x80014b3, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 
+0x80014c5, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 
 0x24420001, 0xaee20174, 0x8ee20174, 0x8f8200d8, 0x8f8300d4, 0x431023, 
 0xaee2725c, 0x8ee2725c, 0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, 
-0xc003fb0, 0x0, 0xc004380, 0xaf800228, 0x8fbf0024, 0x8fb00020, 
+0xc004054, 0x0, 0xc004400, 0xaf800228, 0x8fbf0024, 0x8fb00020, 
 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x3e00008, 0x0, 
-0x2402002c, 0xaf820050, 0xaee07264, 0x8f420238, 0xaee27268, 0x8f820054, 
-0x24420067, 0xaf820058, 0xaee07b78, 0xaee07b7c, 0xaee07b74, 0x3c010001, 
-0x370821, 0xac2083ac, 0x3c010001, 0x370821, 0x3e00008, 0xa02083a9, 
-0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f820054, 0x3c030001, 0x8c634dfc, 
-0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, 0x571021, 0x904283a8, 
-0x10400005, 0x3c030200, 0x3c010001, 0x370821, 0x80014ef, 0xa02083a8, 
-0x8ee20000, 0x431025, 0xaee20000, 0x8f420218, 0x30420100, 0x104000c3, 
-0x0, 0x8f8200b0, 0x30420004, 0x104000bf, 0x0, 0x3c030001, 
-0x771821, 0x8c6383c0, 0x8f820104, 0x146200b1, 0x0, 0x3c030001, 
-0x771821, 0x8c6383c4, 0x8f8200b4, 0x146200ab, 0x0, 0x8f8200b0, 
-0x3c030080, 0x431024, 0x1040000d, 0x0, 0x8f82011c, 0x34420002, 
-0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, 0xaf8200b0, 0x8f82011c, 
-0x2403fffd, 0x431024, 0x80015b5, 0xaf82011c, 0x3c030001, 0x771821, 
-0x8c6383c0, 0x8f820104, 0x1462007f, 0x0, 0x3c030001, 0x771821, 
-0x8c6383c4, 0x8f8200b4, 0x14620079, 0x0, 0x3c070001, 0xf73821, 
-0x8ce783c0, 0x8f8200b0, 0x3c040001, 0x24844430, 0xafa00014, 0xafa20010, 
-0x8f8600b0, 0x3c050005, 0xc0023a7, 0x34a50900, 0x8f82011c, 0x34420002, 
-0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20006, 0x0, 0x8ee201a0, 0x24420001, 0xaee201a0, 
-0x8001589, 0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 
-0x24020400, 0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 
+0x0, 0x0, 0x2402002c, 0xaf820050, 0xaee07264, 0x8f420238, 
+0xaee27268, 0x8f820054, 0x24420067, 0xaf820058, 0xaee07b78, 0xaee07b7c, 
+0xaee07b74, 0x3c010001, 0x370821, 0xac2083ac, 0x3c010001, 0x370821, 
+0x3e00008, 0xa02083a9, 0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f820054, 
+0x3c030001, 0x8c63500c, 0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, 
+0x571021, 0x904283a8, 0x10400005, 0x3c030200, 0x3c010001, 0x370821, 
+0x8001503, 0xa02083a8, 0x8ee20000, 0x431025, 0xaee20000, 0x8f420218, 
+0x30420100, 0x104000c6, 0x0, 0x8f8200b0, 0x30420004, 0x104000c2, 
+0x0, 0x3c030001, 0x771821, 0x8c6383c0, 0x8f820104, 0x146200b4, 
+0x0, 0x3c030001, 0x771821, 0x8c6383c4, 0x8f8200b4, 0x146200ae, 
+0x0, 0x8f8200b0, 0x3c030080, 0x431024, 0x1040000d, 0x0, 
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f8200b0, 0x2403fffb, 0x431024, 
+0xaf8200b0, 0x8f82011c, 0x2403fffd, 0x431024, 0x80015cc, 0xaf82011c, 
+0x3c030001, 0x771821, 0x8c6383c0, 0x8f820104, 0x14620082, 0x0, 
+0x3c030001, 0x771821, 0x8c6383c4, 0x8f8200b4, 0x1462007c, 0x0, 
+0x3c070001, 0xf73821, 0x8ce783c0, 0x8f8200b0, 0x3c040001, 0x24844630, 
+0xafa00014, 0xafa20010, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 
+0xaf8200b0, 0xaf830104, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 
+0x14c20006, 0x0, 0x8ee201a0, 0x24420001, 0xaee201a0, 0x80015a0, 
+0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 0x24020400, 
+0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 0xac650004, 
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x0, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 
+0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 
+0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 
+0x800158a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
+0x80015a0, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 
+0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201d4, 0x3c070001, 
+0xf73821, 0x8ce783c0, 0x24420001, 0xaee201d4, 0x8ee201d4, 0x3c040001, 
+0x2484463c, 0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001, 0x370821, 
+0xac2283c0, 0x8f8200b4, 0x3c070001, 0xf73821, 0x8ce783c0, 0x3c040001, 
+0x24844644, 0x3c010001, 0x370821, 0xac2283c4, 0xafa00010, 0xafa00014, 
+0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x80015cc, 0x0, 
+0x8f820104, 0x3c010001, 0x370821, 0xac2283c0, 0x8f8200b4, 0x3c010001, 
+0x370821, 0xac2283c4, 0x8ee27264, 0x92e304e4, 0x24420067, 0x14600006, 
+0xaee27264, 0x8ee27264, 0x8f430234, 0x43102b, 0x1440007b, 0x0, 
+0x8ee304d4, 0x8ee204e8, 0x14620004, 0x0, 0x92e204e4, 0x50400074, 
+0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 
+0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 
+0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001637, 
+0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 
+0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 
 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 
-0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
-0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
+0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
+0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 
 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 
-0x0, 0x8001573, 0x0, 0x14a00005, 0x0, 0x8f820128, 
+0x0, 0x8001621, 0x0, 0x14a00005, 0x0, 0x8f820128, 
 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x8001589, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 
+0xac800000, 0x8001637, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 
 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 
-0xac820004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201d4, 
-0x3c070001, 0xf73821, 0x8ce783c0, 0x24420001, 0xaee201d4, 0x8ee201d4, 
-0x3c040001, 0x2484443c, 0x80015a6, 0xafa00010, 0x8f820104, 0x3c010001, 
-0x370821, 0xac2283c0, 0x8f8200b4, 0x3c070001, 0xf73821, 0x8ce783c0, 
-0x3c040001, 0x24844444, 0x3c010001, 0x370821, 0xac2283c4, 0xafa00010, 
-0xafa00014, 0x8f8600b0, 0x3c050005, 0xc0023a7, 0x34a50900, 0x80015b5, 
-0x0, 0x8f820104, 0x3c010001, 0x370821, 0xac2283c0, 0x8f8200b4, 
-0x3c010001, 0x370821, 0xac2283c4, 0x8ee27264, 0x92e304e4, 0x24420067, 
-0x14600006, 0xaee27264, 0x8ee27264, 0x8f430234, 0x43102b, 0x14400078, 
-0x0, 0x8ee304d4, 0x8ee204e8, 0x14620004, 0x0, 0x92e204e4, 
-0x50400071, 0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
-0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 
-0x8021, 0x24420001, 0xaee201a0, 0x800161d, 0x8ee201a0, 0x8ee204d4, 
-0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, 
+0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 
+0xac820004, 0x5600000b, 0x24100001, 0x8ee204d4, 0x3c040001, 0x2484464c, 
+0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 
+0x34a5f006, 0x16000003, 0x24020001, 0x8001650, 0xa2e204e4, 0x8ee2016c, 
+0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 
+0xaee07264, 0xaee204e8, 0x8ee20e0c, 0x1040006d, 0x0, 0x8f830120, 
+0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 
+0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 
+0x8021, 0x24420001, 0xaee201a0, 0x80016ad, 0x8ee201a0, 0x8ee2723c, 
+0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 
 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 
 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 
 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 
 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001607, 
+0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001697, 
 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800161d, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80016ad, 
 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 
-0x24100001, 0x8ee204d4, 0x3c040001, 0x2484444c, 0xafa00014, 0xafa20010, 
-0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f006, 0x16000003, 
-0x24020001, 0x8001636, 0xa2e204e4, 0x8ee2016c, 0x24420001, 0xaee2016c, 
-0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, 
-0x8ee20e0c, 0x1040006a, 0x0, 0x8f830120, 0x27623800, 0x24660020, 
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001690, 0x8ee201a0, 
-0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, 
-0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 
-0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 
-0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 
-0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 
-0x800167a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
-0x8001690, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 
-0x5600000b, 0x24100001, 0x8ee2723c, 0x3c040001, 0x24844458, 0xafa00014, 
-0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 
-0x56000001, 0xaee00e0c, 0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 
-0x8ee24e14, 0x10400019, 0x0, 0xaee04e14, 0x8f820040, 0x30420001, 
-0x14400008, 0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, 
-0x8f420264, 0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, 
-0x80016bd, 0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 
-0x24420001, 0xaee20174, 0x8ee20174, 0x8ee27268, 0x2442ff99, 0xaee27268, 
-0x8ee27268, 0x1c400299, 0x0, 0x8f420238, 0x10400296, 0x0, 
-0x8f420080, 0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084, 0xaee20038, 
-0x8f420084, 0xaee20234, 0x8f420088, 0xaee20238, 0x8f42008c, 0xaee2023c, 
-0x8f420090, 0xaee20240, 0x8f420094, 0xaee20244, 0x8f420098, 0xaee20248, 
-0x8f42009c, 0xaee2024c, 0x8f4200a0, 0xaee20250, 0x8f4200a4, 0xaee20254, 
-0x8f4200a8, 0xaee20258, 0x8f4200ac, 0xaee2025c, 0x8f4200b0, 0xaee20260, 
-0x8f4200b4, 0xaee20264, 0x8f4200b8, 0xaee20268, 0x8f4200bc, 0x24040001, 
-0xaee2026c, 0xaee0003c, 0x41080, 0x571021, 0x8ee3003c, 0x8c420234, 
-0x24840001, 0x621821, 0x2c82000f, 0xaee3003c, 0x1440fff8, 0x41080, 
-0x8f4200cc, 0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120, 0x27623800, 
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001750, 
-0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 0xac620008, 0x24020400, 
-0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 0xac640000, 0xac650004, 
-0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 
-0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 
-0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 
-0x800173a, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
-0x8001750, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 
-0x12000206, 0x3c020400, 0xafa20018, 0x3c020001, 0x571021, 0x904283a0, 
-0x10400105, 0x0, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 
-0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 
-0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 
-0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 0x240f000d, 
-0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 
-0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, 
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80017cb, 0x8ee201a0, 
-0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 
-0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 
-0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 
-0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 
-0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
-0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
-0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
-0x80017b8, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 
-0x80017cb, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 
-0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, 
-0x14620074, 0x3c050009, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 
-0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 0x240c0011, 
-0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001834, 0x8ee201a0, 
-0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 
-0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 
-0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 0x8ee34e20, 
-0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 
-0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10620005, 0x0, 0x8001821, 0x0, 0x14600005, 
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400010, 0xac800000, 0x8001834, 0x0, 0x8ee24e20, 
-0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 0xac8a0004, 
-0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, 
-0x0, 0x316300ff, 0x24020001, 0x14620003, 0x3c050009, 0x800194b, 
-0x24100001, 0x3c040001, 0x24844464, 0xafa00010, 0xafa00014, 0x8f860120, 
-0x8f870124, 0x8001850, 0x34a5f011, 0x3c040001, 0x24844470, 0xafa00010, 
-0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, 0xc0023a7, 0x8021, 
-0x800194b, 0x0, 0x3c040001, 0x2484447c, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0x8001944, 0x34a5f00f, 0x8ee205f8, 0x8f430228, 
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, 
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 
+0x24100001, 0x8ee2723c, 0x3c040001, 0x24844658, 0xafa00014, 0xafa20010, 
+0x8ee6723c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001, 
+0xaee00e0c, 0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x8ee24e14, 
+0x10400019, 0x0, 0xaee04e14, 0x8f820040, 0x30420001, 0x14400008, 
+0x0, 0x8f430104, 0x24020001, 0x10620004, 0x0, 0x8f420264, 
+0x10400006, 0x0, 0x8ee20178, 0x24420001, 0xaee20178, 0x80016da, 
+0x8ee20178, 0x8f820044, 0x34420004, 0xaf820044, 0x8ee20174, 0x24420001, 
+0xaee20174, 0x8ee20174, 0x8ee27268, 0x2442ff99, 0xaee27268, 0x8ee27268, 
+0x1c4002a8, 0x0, 0x8f420238, 0x104002a5, 0x0, 0x8f420080, 
+0xaee2004c, 0x8f4200c0, 0xaee20048, 0x8f420084, 0xaee20038, 0x8f420084, 
+0xaee20234, 0x8f420088, 0xaee20238, 0x8f42008c, 0xaee2023c, 0x8f420090, 
+0xaee20240, 0x8f420094, 0xaee20244, 0x8f420098, 0xaee20248, 0x8f42009c, 
+0xaee2024c, 0x8f4200a0, 0xaee20250, 0x8f4200a4, 0xaee20254, 0x8f4200a8, 
+0xaee20258, 0x8f4200ac, 0xaee2025c, 0x8f4200b0, 0xaee20260, 0x8f4200b4, 
+0xaee20264, 0x8f4200b8, 0xaee20268, 0x8f4200bc, 0x24040001, 0xaee2026c, 
+0xaee0003c, 0x41080, 0x571021, 0x8ee3003c, 0x8c420234, 0x24840001, 
+0x621821, 0x2c82000f, 0xaee3003c, 0x1440fff8, 0x41080, 0x8f4200cc, 
+0xaee20050, 0x8f4200d0, 0xaee20054, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 
+0xaee201a0, 0x8001770, 0x8ee201a0, 0x8f440208, 0x8f45020c, 0x26e20030, 
+0xac620008, 0x24020400, 0xa462000e, 0x2402000f, 0xac620018, 0xac60001c, 
+0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 
+0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
+0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 
+0x10a20005, 0x0, 0x800175a, 0x0, 0x14a00005, 0x0, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
+0x50400013, 0xac800000, 0x8001770, 0x0, 0x8ee24e20, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 
+0x24020001, 0xac820004, 0x12000212, 0x3c020400, 0xafa20018, 0x3c020001, 
+0x571021, 0x904283a0, 0x1040010b, 0x0, 0x8ee205f8, 0x8f430228, 
+0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, 
+0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 
+0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, 
+0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 
 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
-0x15020007, 0x1021, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 
-0x80018c9, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, 
+0x8021, 0x24420001, 0xaee201a0, 0x80017ee, 0x8ee201a0, 0x8ee405f8, 
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f8000e, 
+0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008, 
+0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 0x24100001, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80017db, 
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80017ee, 
+0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 
+0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x14620077, 
+0x3c050009, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 
+0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 0x24080012, 
+0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 
+0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 
+0x800185a, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 
+0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001847, 
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x800185a, 
+0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0xac880000, 0xac8a0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 
+0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x14620003, 
+0x3c050009, 0x8001977, 0x24100001, 0x3c040001, 0x24844664, 0xafa00010, 
+0xafa00014, 0x8f860120, 0x8f870124, 0x8001876, 0x34a5f011, 0x3c040001, 
+0x24844670, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, 
+0xc002403, 0x8021, 0x8001977, 0x0, 0x3c040001, 0x2484467c, 
+0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x8001970, 0x34a5f00f, 
+0x8ee205f8, 0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 
+0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 
+0xac440600, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 
+0x27683000, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 
+0x1021, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80018f2, 
+0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 
+0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 
+0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 
+0xaf880120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 
+0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 
+0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80018dc, 0x0, 
+0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80018f2, 0x0, 
+0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, 0xaee905f8, 
+0x3c040001, 0x24844688, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 
+0x3c050009, 0xc002403, 0x34a5f000, 0x8001977, 0x0, 0x8f830120, 
+0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 
+0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 
+0x8021, 0x24420001, 0xaee201a0, 0x8001959, 0x8ee201a0, 0x8ee205f8, 
+0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 
+0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 
+0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 
 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80018b3, 
+0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8001943, 
 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80018c9, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8001959, 
 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, 
-0xaee905f8, 0x3c040001, 0x24844488, 0xafa00010, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800194b, 0x0, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 
-0xaee201a0, 0x800192d, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
-0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
-0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
-0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 
-0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
-0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10a20005, 0x0, 0x8001917, 0x0, 0x14a00005, 
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400013, 0xac800000, 0x800192d, 0x0, 0x8ee24e20, 
-0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 
-0xac820000, 0x24020001, 0xac820004, 0x5600001d, 0x24100001, 0x3c040001, 
-0x24844490, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800194b, 
-0x8ee201ac, 0x3c040001, 0x2484449c, 0xafa00014, 0x8ee605f8, 0x8f470228, 
-0x3c050009, 0x34a5f005, 0xc0023a7, 0x0, 0x8ee201a8, 0x8021, 
-0x24420001, 0xaee201a8, 0x8ee201a8, 0x1200000c, 0x24020001, 0x3c010001, 
-0x370821, 0xa02083a0, 0x8f420238, 0x8ee30154, 0x24630001, 0xaee30154, 
-0x8ee30154, 0x800195b, 0xaee27268, 0x24020001, 0x3c010001, 0x370821, 
-0xa02283a0, 0x3c020001, 0x8c424dfc, 0x10400181, 0x0, 0x8ee27b74, 
-0x24430001, 0x284200c9, 0x1440019e, 0xaee37b74, 0x8ee204c4, 0x30420002, 
-0x14400113, 0xaee07b74, 0x8ee204c4, 0x3c030600, 0x34631000, 0x34420002, 
-0xaee204c4, 0xafa30018, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 
-0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 
-0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 
-0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 0x240f000d, 
-0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 
-0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, 
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x80019e1, 0x8ee201a0, 
-0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 
-0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 
-0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 
-0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 
-0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
-0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
-0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
-0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
-0x80019ce, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 
-0x80019e1, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 
-0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, 
-0x54620075, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 
-0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 0x240c0011, 
-0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 
-0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8001a4a, 0x8ee201a0, 
-0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 
-0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 
-0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 0x8ee34e20, 
-0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 
-0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10620005, 0x0, 0x8001a37, 0x0, 0x14600005, 
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400010, 0xac800000, 0x8001a4a, 0x0, 0x8ee24e20, 
-0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 0xac8a0004, 
-0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, 
-0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, 
-0x24844464, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 
-0xc0023a7, 0x34a5f011, 0x8001a76, 0x0, 0x3c040001, 0x24844470, 
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f010, 
-0x8001a76, 0x0, 0x3c040001, 0x2484447c, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 0x24420001, 
-0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, 0xaee20158, 0x8ee20158, 
-0x8ee204c4, 0x30420001, 0x10400055, 0x0, 0x8f420218, 0x30420080, 
-0x10400029, 0x0, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b6c, 
-0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 0x2021, 
-0x461024, 0x1444000d, 0x671824, 0x1465000b, 0x0, 0x8ee27b70, 
-0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 0x14440003, 
-0x671824, 0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0, 
-0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420020, 0x8001b01, 
-0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 0x8001b01, 0xaf820044, 
-0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044, 0x8ee27b6c, 0x402821, 
-0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 0x2021, 0x461024, 
-0x1444000d, 0x671824, 0x1465000b, 0x0, 0x8ee27b70, 0x402821, 
-0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 0x14440003, 0x671824, 
-0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 0x8ee400e0, 0x8ee500e4, 
-0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420040, 0x8001b01, 0xaf820044, 
-0x8f820044, 0x34420040, 0x8001b01, 0xaf820044, 0x8f820044, 0x34420040, 
-0xaf820044, 0x8ee27b7c, 0x24430001, 0x28420015, 0x14400028, 0xaee37b7c, 
-0x8f820044, 0x38420020, 0xaf820044, 0x8001b01, 0xaee07b7c, 0x8ee204c4, 
-0x30420001, 0x10400011, 0x0, 0x8f420218, 0x30420080, 0x10400009, 
-0x0, 0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 0x2403ffbf, 
-0x431024, 0x8001aff, 0xaf820044, 0x8f820044, 0x34420060, 0x8001aff, 
-0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b78, 0x24430001, 
-0x28421389, 0x14400005, 0xaee37b78, 0x8f820044, 0x38420020, 0xaf820044, 
-0xaee07b78, 0xc0044fc, 0x0, 0x8fbf0024, 0x8fb00020, 0x3e00008, 
-0x27bd0028, 0x0, 0x0, 0x0, 0x27bdffb8, 0xafbf0044, 
+0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600001d, 
+0x24100001, 0x3c040001, 0x24844690, 0xafa00010, 0xafa00014, 0x8ee605f8, 
+0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 
+0xaee201ac, 0x8001977, 0x8ee201ac, 0x3c040001, 0x2484469c, 0xafa00014, 
+0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc002403, 0x0, 
+0x8ee201a8, 0x8021, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x1200000c, 
+0x24020001, 0x3c010001, 0x370821, 0xa02083a0, 0x8f420238, 0x8ee30154, 
+0x24630001, 0xaee30154, 0x8ee30154, 0x8001987, 0xaee27268, 0x24020001, 
+0x3c010001, 0x370821, 0xa02283a0, 0x3c020001, 0x8c42500c, 0x10400187, 
+0x0, 0x8ee27b74, 0x24430001, 0x284200c9, 0x144001a4, 0xaee37b74, 
+0x8ee204c4, 0x30420002, 0x14400119, 0xaee07b74, 0x8ee204c4, 0x3c030600, 
+0x34631000, 0x34420002, 0xaee204c4, 0xafa30018, 0x8ee205f8, 0x8f430228, 
+0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, 
+0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 
+0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, 
+0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 
+0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, 
+0x8021, 0x24420001, 0xaee201a0, 0x8001a10, 0x8ee201a0, 0x8ee405f8, 
+0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f8000e, 
+0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008, 
+0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 0x24100001, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80019fd, 
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001a10, 
+0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0xac8d0000, 0xac8e0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 
+0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x54620078, 
+0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 
+0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 0x24080012, 
+0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 
+0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 
+0x8001a7c, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 
+0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24100001, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001a69, 
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001a7c, 
+0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0xac880000, 0xac8a0004, 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 
+0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, 
+0x0, 0x3c040001, 0x24844664, 0xafa00010, 0xafa00014, 0x8f860120, 
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001aa8, 0x0, 
+0x3c040001, 0x24844670, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 
+0xc002403, 0x34a5f010, 0x8001aa8, 0x0, 0x3c040001, 0x2484467c, 
+0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 
+0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, 
+0xaee20158, 0x8ee20158, 0x8ee204c4, 0x30420001, 0x10400055, 0x0, 
+0x8f420218, 0x30420080, 0x10400029, 0x0, 0x8f820044, 0x34420040, 
+0xaf820044, 0x8ee27b6c, 0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 
+0x2407ffff, 0x2021, 0x461024, 0x1444000d, 0x671824, 0x1465000b, 
+0x0, 0x8ee27b70, 0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 
+0x461024, 0x14440003, 0x671824, 0x1065000b, 0x0, 0x8ee200c0, 
+0x8ee300c4, 0x8ee400e0, 0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 
+0x38420020, 0x8001b33, 0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 
+0x8001b33, 0xaf820044, 0x8f820044, 0x2403ffdf, 0x431024, 0xaf820044, 
+0x8ee27b6c, 0x402821, 0x8ee200c0, 0x8ee300c4, 0x24060000, 0x2407ffff, 
+0x2021, 0x461024, 0x1444000d, 0x671824, 0x1465000b, 0x0, 
+0x8ee27b70, 0x402821, 0x8ee200e0, 0x8ee300e4, 0x2021, 0x461024, 
+0x14440003, 0x671824, 0x1065000b, 0x0, 0x8ee200c0, 0x8ee300c4, 
+0x8ee400e0, 0x8ee500e4, 0xaee37b6c, 0xaee57b70, 0x8f820044, 0x38420040, 
+0x8001b33, 0xaf820044, 0x8f820044, 0x34420040, 0x8001b33, 0xaf820044, 
+0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b7c, 0x24430001, 0x28420015, 
+0x14400028, 0xaee37b7c, 0x8f820044, 0x38420020, 0xaf820044, 0x8001b33, 
+0xaee07b7c, 0x8ee204c4, 0x30420001, 0x10400011, 0x0, 0x8f420218, 
+0x30420080, 0x10400009, 0x0, 0x8f820044, 0x34420020, 0xaf820044, 
+0x8f820044, 0x2403ffbf, 0x431024, 0x8001b31, 0xaf820044, 0x8f820044, 
+0x34420060, 0x8001b31, 0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, 
+0x8ee27b78, 0x24430001, 0x28421389, 0x14400005, 0xaee37b78, 0x8f820044, 
+0x38420020, 0xaf820044, 0xaee07b78, 0xc00457c, 0x0, 0x8fbf0024, 
+0x8fb00020, 0x3e00008, 0x27bd0028, 0x0, 0x27bdffb8, 0xafbf0044, 
 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, 0xafb20030, 0xafb1002c, 
 0xafb00028, 0x8f960064, 0x32c20004, 0x1040000c, 0x24020004, 0xaf820064, 
 0x8f420114, 0xaee204d0, 0x8f820060, 0x34420008, 0xaf820060, 0x8ee20168, 
-0x24420001, 0xaee20168, 0x8002293, 0x8ee20168, 0x32c20001, 0x10400004, 
-0x24020001, 0xaf820064, 0x8002293, 0x0, 0x32c20002, 0x1040076b, 
-0x0, 0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, 
-0x21080, 0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, 
-0x24420001, 0x3042003f, 0x8001b41, 0xaf42022c, 0x3c040001, 0x24844510, 
-0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003, 0xc0023a7, 0x34a5f01f, 
-0x3821, 0x14e00003, 0x0, 0x800228c, 0xaf960064, 0x93a20020, 
-0x2443ffff, 0x2c620011, 0x1040063c, 0x31080, 0x3c010001, 0x220821, 
-0x8c2245c8, 0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20dfc, 
-0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, 
-0x8002287, 0x8ee20118, 0x8fa20020, 0x24030001, 0x3c010001, 0x370821, 
-0xa02383a1, 0x30420fff, 0xaee25228, 0x8f820060, 0x34420100, 0xaf820060, 
-0x8ee20144, 0x24420001, 0xaee20144, 0x8002287, 0x8ee20144, 0x8fa20020, 
-0x21200, 0x22502, 0x24020001, 0x10820005, 0x24020002, 0x10820009, 
-0x2402fffe, 0x8001b8a, 0xafa00010, 0x8ee204c4, 0xaee40070, 0xaee40074, 
-0x34420001, 0x8001b7e, 0xaee204c4, 0x8ee304c4, 0xaee40070, 0xaee40074, 
-0x621824, 0xaee304c4, 0x8f840054, 0x41442, 0x41c82, 0x431021, 
-0x41cc2, 0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 
-0x8001b91, 0xaee20078, 0x3c040001, 0x2484451c, 0xafa00014, 0x8fa60020, 
-0x3c050003, 0xc0023a7, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, 
-0x8002287, 0x8ee20110, 0x27440212, 0xc00229d, 0x24050006, 0x3049001f, 
-0x920c0, 0x2e41021, 0x9442726c, 0x30424000, 0x1040000a, 0x971021, 
-0x97430212, 0xa443726e, 0x8f430214, 0x971021, 0xac437270, 0x2e41821, 
-0x34028000, 0x8001c38, 0xa462726c, 0x9443726e, 0x97420212, 0x14620006, 
-0x2e41021, 0x971021, 0x8c437270, 0x8f420214, 0x1062009d, 0x2e41021, 
-0x9442726c, 0x30428000, 0x10400028, 0x2406ffff, 0x2021, 0x410c0, 
-0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, 
-0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010, 0x620c0, 0x610c0, 
-0x571821, 0x8c63736c, 0x571021, 0xafa30010, 0x8c427370, 0x3c040001, 
-0x24844528, 0xafa20014, 0x8f470214, 0x3c050003, 0xc0023a7, 0x34a50013, 
-0x8001c4f, 0x3c020800, 0x97430212, 0x971021, 0xa443736e, 0x8f430214, 
-0x971021, 0xac437370, 0x910c0, 0x2e21021, 0x2e41821, 0x8001c36, 
-0xa446726c, 0x2e41021, 0x9445726c, 0x8001bed, 0x510c0, 0x9443736e, 
-0x97420212, 0x14620006, 0x510c0, 0x971021, 0x8c437370, 0x8f420214, 
-0x10620065, 0x510c0, 0x2e21021, 0x9445736c, 0x510c0, 0x2e21021, 
-0x9442736c, 0x30428000, 0x1040fff0, 0x971021, 0x520c0, 0x971021, 
-0x9443736e, 0x97420212, 0x14620006, 0x2406ffff, 0x971021, 0x8c437370, 
-0x8f420214, 0x10620053, 0x3c020800, 0x2021, 0x410c0, 0x2e21021, 
+0x24420001, 0xaee20168, 0x80022ee, 0x8ee20168, 0x32c20001, 0x10400004, 
+0x24020001, 0xaf820064, 0x80022ee, 0x0, 0x32c20002, 0x1440000c, 
+0x3c050003, 0x3c040001, 0x24844714, 0x34a50001, 0x2c03021, 0x3821, 
+0xafa00010, 0xc002403, 0xafa00014, 0x2402fff8, 0x80022ee, 0xaf820064, 
+0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, 0x21080, 
+0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, 0x24420001, 
+0x3042003f, 0x8001b7c, 0xaf42022c, 0x3c040001, 0x24844720, 0xafa00014, 
+0x8f46022c, 0x8f47010c, 0x3c050003, 0xc002403, 0x34a5f01f, 0x3821, 
+0x14e00003, 0x0, 0x80022e7, 0xaf960064, 0x93a20020, 0x2443ffff, 
+0x2c620011, 0x10400656, 0x31080, 0x3c010001, 0x220821, 0x8c2247d8, 
+0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20dfc, 0x8f820060, 
+0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, 0x80022e2, 
+0x8ee20118, 0x8fa20020, 0x24030001, 0x3c010001, 0x370821, 0xa02383a1, 
+0x30420fff, 0xaee25228, 0x8f820060, 0x34420100, 0xaf820060, 0x8ee20144, 
+0x24420001, 0xaee20144, 0x80022e2, 0x8ee20144, 0x8fa20020, 0x21200, 
+0x22502, 0x24020001, 0x10820005, 0x24020002, 0x10820009, 0x2402fffe, 
+0x8001bc5, 0xafa00010, 0x8ee204c4, 0xaee40070, 0xaee40074, 0x34420001, 
+0x8001bb9, 0xaee204c4, 0x8ee304c4, 0xaee40070, 0xaee40074, 0x621824, 
+0xaee304c4, 0x8f840054, 0x41442, 0x41c82, 0x431021, 0x41cc2, 
+0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 0x8001bcc, 
+0xaee20078, 0x3c040001, 0x2484472c, 0xafa00014, 0x8fa60020, 0x3c050003, 
+0xc002403, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, 0x80022e2, 
+0x8ee20110, 0x27440212, 0xc0022f8, 0x24050006, 0x3049001f, 0x920c0, 
+0x2e41021, 0x9442726c, 0x30424000, 0x1040000a, 0x971021, 0x97430212, 
+0xa443726e, 0x8f430214, 0x971021, 0xac437270, 0x2e41821, 0x34028000, 
+0x8001c75, 0xa462726c, 0x9443726e, 0x97420212, 0x14620006, 0x2e41021, 
+0x971021, 0x8c437270, 0x8f420214, 0x1062009f, 0x2e41021, 0x9442726c, 
+0x30428000, 0x1040002a, 0x2406ffff, 0x2021, 0x410c0, 0x2e21021, 
 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, 0x2c820080, 
-0x1440fff8, 0x410c0, 0x4c10023, 0x620c0, 0x910c0, 0x571821, 
-0x8c63726c, 0x571021, 0xafa30010, 0x8c427270, 0x3c040001, 0x24844534, 
-0xafa20014, 0x8f470214, 0x3c050003, 0xc0023a7, 0x34a5f017, 0x8001c4f, 
-0x3c020800, 0x8f430210, 0xb71021, 0xac43776c, 0x8f430214, 0xb71021, 
-0xac437770, 0x3c020001, 0x571021, 0x8c4283a4, 0x24420001, 0x3c010001, 
-0x370821, 0xac2283a4, 0x3c030001, 0x771821, 0x8c6383a4, 0x2e51021, 
-0x8001c41, 0xa443776c, 0x97430212, 0x971021, 0xa443736e, 0x8f430214, 
-0x971021, 0xac437370, 0x510c0, 0x2e21021, 0x2e41821, 0xa446736c, 
-0x34028000, 0xa462736c, 0x2021, 0x428c0, 0x2e51021, 0x9442776c, 
-0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa, 0x428c0, 0x92e204c8, 
-0x10400006, 0x24020001, 0x8ee304cc, 0x1221004, 0x621825, 0x8001c4e, 
-0xaee304cc, 0x8f830228, 0x24020001, 0x1221004, 0x621825, 0xaf830228, 
-0x3c020800, 0x34421000, 0xafa20018, 0x8ee205f8, 0x8f430228, 0x24420001, 
-0x304a00ff, 0x514300f7, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 
-0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 
-0x24690032, 0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24100008, 
-0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 
-0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 
-0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001cc4, 
-0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 
-0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 
-0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 
-0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 
-0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8001cb1, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
-0xac800000, 0x8001cc4, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 
-0x24020001, 0x54620075, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 
-0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240e0008, 
-0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 
-0x0, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001d2d, 
-0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 
-0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4, 
-0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f, 0x0, 
-0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 
-0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007, 0x0, 
-0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001d1a, 0x0, 
-0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d2d, 0x0, 
-0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20, 0x24420001, 
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8a0000, 
-0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 
-0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, 
-0x3c040001, 0x24844540, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
-0x3c050009, 0xc0023a7, 0x34a5f011, 0x8001d59, 0x0, 0x3c040001, 
-0x2484454c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 
-0x34a5f010, 0x8001d59, 0x0, 0x3c040001, 0x24844558, 0xafa00014, 
-0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 
-0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20124, 0x24420001, 0xaee20124, 
-0x8001f47, 0x8ee20124, 0x27440212, 0xc00229d, 0x24050006, 0x3049001f, 
-0x928c0, 0x2e51021, 0x9442726c, 0x30428000, 0x1040002d, 0xb71021, 
-0x9443726e, 0x97420212, 0x1462001a, 0xb71021, 0x8c437270, 0x8f420214, 
-0x54620018, 0xafa20010, 0x92e204c8, 0x10400007, 0x24020001, 0x8ee304cc, 
-0x1221004, 0x21027, 0x621824, 0x8001d7e, 0xaee304cc, 0x8f830228, 
-0x1221004, 0x21027, 0x621824, 0xaf830228, 0x918c0, 0x2e31021, 
-0x9442726c, 0x2e31821, 0x34424000, 0x8001e04, 0xa462726c, 0x8f420214, 
-0xafa20010, 0x910c0, 0x571021, 0x8c42726c, 0x3c040001, 0x24844564, 
-0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c, 0xc0023a7, 0x1203021, 
-0x8001e39, 0x3c020800, 0x9443726e, 0x97420212, 0x14620019, 0x918c0, 
-0xb71021, 0x8c437270, 0x8f420214, 0x14620014, 0x918c0, 0x2e51021, 
-0x9447726c, 0x720c0, 0x971021, 0x9443736e, 0xb71021, 0xa443726e, 
-0x971021, 0x8c437370, 0xb71021, 0xac437270, 0x2e41021, 0x9443736c, 
-0x2e51021, 0xa443726c, 0x2e41821, 0x24024000, 0x8001e04, 0xa462736c, 
-0x2e31021, 0x9447726c, 0x3021, 0x720c0, 0x2e41021, 0x9442736c, 
-0x4021, 0x30428000, 0x14400025, 0xe02821, 0x605021, 0x240b4000, 
-0x971021, 0x9443736e, 0x97420212, 0x54620015, 0xe02821, 0x971021, 
-0x8c437370, 0x8f420214, 0x54620010, 0xe02821, 0x11000006, 0x2e41021, 
-0x9443736c, 0x510c0, 0x2e21021, 0x8001dd0, 0xa443736c, 0x9443736c, 
-0x2ea1021, 0xa443726c, 0x710c0, 0x2e21021, 0xa44b736c, 0x8001dde, 
-0x24060001, 0x510c0, 0x2e21021, 0x9447736c, 0x720c0, 0x2e41021, 
-0x9442736c, 0x30428000, 0x1040ffdf, 0x25080001, 0x30c200ff, 0x14400025, 
-0x2021, 0x720c0, 0x971021, 0x9443736e, 0x97420212, 0x1462000f, 
-0x910c0, 0x971021, 0x8c437370, 0x8f420214, 0x1462000a, 0x910c0, 
-0x2e41821, 0x24024000, 0x15000015, 0xa462736c, 0x910c0, 0x2e21821, 
-0x34028000, 0x8001e04, 0xa462726c, 0x571021, 0x8c42726c, 0x3c040001, 
-0x24844570, 0x3c050003, 0xafa20010, 0x710c0, 0x571021, 0x8c42736c, 
-0x34a5001e, 0x1203021, 0xc0023a7, 0xafa20014, 0x8001e39, 0x3c020800, 
-0x2021, 0x428c0, 0xb71021, 0x9443776e, 0x97420212, 0x5462002b, 
-0x24840001, 0xb71021, 0x8c437770, 0x8f420214, 0x54620026, 0x24840001, 
-0x3c020001, 0x571021, 0x8c4283a4, 0x2442ffff, 0x3c010001, 0x370821, 
-0xac2283a4, 0x3c020001, 0x571021, 0x8c4283a4, 0x809021, 0x242102b, 
-0x1040000e, 0x24b1776c, 0x24b07774, 0x2f02021, 0x2f12821, 0xc002434, 
-0x24060008, 0x26310008, 0x3c020001, 0x571021, 0x8c4283a4, 0x26520001, 
-0x242102b, 0x1440fff5, 0x26100008, 0x3c040001, 0x972021, 0x8c8483a4, 
-0x24050008, 0x420c0, 0x2484776c, 0xc00242c, 0x2e42021, 0x8001e39, 
-0x3c020800, 0x2c820080, 0x1440ffcf, 0x428c0, 0x3c020800, 0x34422000, 
-0xafa20018, 0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 0x514300f7, 
-0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 
-0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 
-0x2c420033, 0x10400067, 0x5821, 0x24100008, 0x240f000d, 0x240d0007, 
-0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 
-0x50400001, 0x27683000, 0x8f820128, 0x15020007, 0x1021, 0x8ee201a0, 
-0x3821, 0x24420001, 0xaee201a0, 0x8001eae, 0x8ee201a0, 0x8ee405f8, 
+0x1440fff8, 0x410c0, 0x4c10010, 0x618c0, 0x610c0, 0x571821, 
+0x8c63736c, 0x571021, 0xafa30010, 0x8c427370, 0x3c040001, 0x24844738, 
+0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a50013, 0x8001c8c, 
+0x3c020800, 0x97440212, 0x771021, 0xa444736e, 0x8f440214, 0x771021, 
+0x2e31821, 0xac447370, 0x34028000, 0xa462736c, 0x910c0, 0x2e21021, 
+0x8001c75, 0xa446726c, 0x2e41021, 0x9445726c, 0x8001c2a, 0x510c0, 
+0x9443736e, 0x97420212, 0x14620006, 0x510c0, 0x971021, 0x8c437370, 
+0x8f420214, 0x10620065, 0x510c0, 0x2e21021, 0x9445736c, 0x510c0, 
+0x2e21021, 0x9442736c, 0x30428000, 0x1040fff0, 0x971021, 0x520c0, 
+0x971021, 0x9443736e, 0x97420212, 0x14620006, 0x2406ffff, 0x971021, 
+0x8c437370, 0x8f420214, 0x10620053, 0x3c020800, 0x2021, 0x410c0, 
+0x2e21021, 0x9442736c, 0x30424000, 0x54400005, 0x803021, 0x24840001, 
+0x2c820080, 0x1440fff8, 0x410c0, 0x4c10023, 0x618c0, 0x910c0, 
+0x571821, 0x8c63726c, 0x571021, 0xafa30010, 0x8c427270, 0x3c040001, 
+0x24844744, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a5f017, 
+0x8001c8c, 0x3c020800, 0x8f430210, 0xb71021, 0xac43776c, 0x8f430214, 
+0xb71021, 0xac437770, 0x3c020001, 0x571021, 0x8c4283a4, 0x24420001, 
+0x3c010001, 0x370821, 0xac2283a4, 0x3c030001, 0x771821, 0x8c6383a4, 
+0x2e51021, 0x8001c7e, 0xa443776c, 0x97440212, 0x771021, 0xa444736e, 
+0x8f440214, 0x771021, 0x2e31821, 0xac447370, 0x34028000, 0xa462736c, 
+0x510c0, 0x2e21021, 0xa446736c, 0x2021, 0x428c0, 0x2e51021, 
+0x9442776c, 0x1040ffdc, 0x24840001, 0x2c820080, 0x5440fffa, 0x428c0, 
+0x92e204c8, 0x10400006, 0x24020001, 0x8ee304cc, 0x1221004, 0x621825, 
+0x8001c8b, 0xaee304cc, 0x8f830228, 0x24020001, 0x1221004, 0x621825, 
+0xaf830228, 0x3c020800, 0x34421000, 0xafa20018, 0x8ee205f8, 0x8f430228, 
+0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 0x210c0, 
+0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 
+0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 0x5821, 
+0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 
+0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
+0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 0x8ee201a0, 
+0x3821, 0x24420001, 0xaee201a0, 0x8001d04, 0x8ee201a0, 0x8ee405f8, 
 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 
 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 0xa4f0000e, 
 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 0xace20008, 
@@ -635,707 +564,800 @@
 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 
 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001e9b, 
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001cf1, 
 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001eae, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d04, 
 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 
 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 
-0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 0x24020001, 0x54620075, 
+0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 0x54620078, 
 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 
-0x2c420033, 0x1040005e, 0x5821, 0x240e0008, 0x240d0011, 0x240a0012, 
+0x2c420033, 0x10400061, 0x5821, 0x240e0008, 0x240d0011, 0x240a0012, 
 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
-0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 
-0x3821, 0x24420001, 0xaee201a0, 0x8001f17, 0x8ee201a0, 0x8ee205f8, 
-0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 
-0xac6d0018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
-0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
-0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
-0x8ee34e20, 0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001, 
-0x10620005, 0x0, 0x8001f04, 0x0, 0x14600005, 0x0, 
-0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
-0x50400010, 0xac800000, 0x8001f17, 0x0, 0x8ee24e20, 0x24420001, 
-0x50480003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 
-0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa9, 0x0, 
-0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, 0x24844540, 
-0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 
-0x34a5f011, 0x8001f43, 0x0, 0x3c040001, 0x2484454c, 0xafa00014, 
-0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f010, 0x8001f43, 
-0x0, 0x3c040001, 0x24844558, 0xafa00014, 0x8ee605f8, 0x8f470228, 
-0x3c050009, 0xc0023a7, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 
-0x8ee201a8, 0x8ee20128, 0x24420001, 0xaee20128, 0x8ee20128, 0x8ee20160, 
-0x24420001, 0xaee20160, 0x8002287, 0x8ee20160, 0x8fa20020, 0x21200, 
-0x21d02, 0x24020001, 0x10620005, 0x24020002, 0x1062000d, 0x0, 
-0x8001f67, 0xafa00010, 0x92e204c8, 0x14400006, 0x24020001, 0x8f820228, 
-0xaee204cc, 0x2402ffff, 0xaf820228, 0x24020001, 0x8001f6e, 0xa2e204c8, 
-0x92e204c8, 0x5040000c, 0xa2e004c8, 0x8ee204cc, 0xaf820228, 0x8001f6e, 
-0xa2e004c8, 0x3c040001, 0x24844578, 0xafa00014, 0x8fa60020, 0x3c050003, 
-0xc0023a7, 0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c, 0x8002287, 
-0x8ee2013c, 0x8fa20020, 0x21200, 0x22502, 0x24020001, 0x10820005, 
-0x24020002, 0x1082000f, 0x0, 0x8001f93, 0xafa00010, 0x8f820220, 
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001, 
-0x3c010001, 0x370821, 0xa02283a2, 0x8001f9a, 0xaee40108, 0x8f820220, 
-0x3c0308ff, 0x3463fff7, 0x431024, 0xaf820220, 0x3c010001, 0x370821, 
-0xa02083a2, 0x8001f9a, 0xaee40108, 0x3c040001, 0x24844584, 0xafa00014, 
-0x8fa60020, 0x3c050003, 0xc0023a7, 0x34a5f00a, 0x8ee2012c, 0x24420001, 
-0xaee2012c, 0x8002287, 0x8ee2012c, 0x8fa20020, 0x21200, 0x21d02, 
-0x24020001, 0x10620005, 0x24020002, 0x1062000e, 0x0, 0x8001fc1, 
-0xafa00010, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 
-0xaf820220, 0x24020001, 0x3c010001, 0x370821, 0x8001fc8, 0xa02283a3, 
-0x3c020001, 0x571021, 0x904283a2, 0x3c010001, 0x370821, 0x1440000e, 
-0xa02083a3, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0x8001fc8, 
-0xaf820220, 0x3c040001, 0x24844590, 0xafa00014, 0x8fa60020, 0x3c050003, 
-0xc0023a7, 0x34a5f00b, 0x8ee20114, 0x24420001, 0xaee20114, 0x8002287, 
-0x8ee20114, 0x27840208, 0x27450200, 0xc00243e, 0x24060008, 0x26e40094, 
-0x27450200, 0xc00243e, 0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, 
-0x8002287, 0x8ee20134, 0x8f460248, 0x24040001, 0xc004e2c, 0x24050004, 
-0x8ee20130, 0x24420001, 0xaee20130, 0x8002287, 0x8ee20130, 0x8ef301c4, 
-0x8ef401c8, 0x8ef501cc, 0x8ee20140, 0x26e40030, 0x24420001, 0xaee20140, 
-0x8ef00140, 0x8ef10074, 0x8ef20070, 0xc00242c, 0x24050400, 0xaef301c4, 
-0xaef401c8, 0xaef501cc, 0xaef00140, 0xaef10074, 0xaef20070, 0x8f42025c, 
-0x26e40094, 0xaee20060, 0x8f420260, 0x27450200, 0x24060008, 0xaee20068, 
-0x24020006, 0xc00243e, 0xaee20064, 0x3c023b9a, 0x3442ca00, 0xaee2006c, 
-0x240203e8, 0x24040002, 0x24030001, 0xaee20104, 0xaee40100, 0xaee3010c, 
-0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaee30108, 0x8002011, 
-0x2021, 0xaee40108, 0x2021, 0x3c030001, 0x641821, 0x90634d50, 
-0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 
-0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, 
-0x2e41021, 0x8002287, 0xa040009c, 0x240a0400, 0x24090040, 0x24080001, 
-0x8f830100, 0x27623000, 0x24660020, 0xc2102b, 0x50400001, 0x27662800, 
-0x8f820108, 0x14c20007, 0x26e20030, 0x8ee201a4, 0x3821, 0x24420001, 
-0xaee201a4, 0x8002050, 0x8ee201a4, 0x8ee404a8, 0x8ee504ac, 0xac620008, 
-0xa46a000e, 0xac600018, 0xac60001c, 0xac640000, 0xac650004, 0x8ee204bc, 
-0xac620010, 0xaf860100, 0x92e204dc, 0x1440000e, 0x24070001, 0x8ee24e18, 
-0x24420001, 0x50490003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 
-0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21021, 0xac400000, 0xac480004, 
-0x10e0ffd5, 0x0, 0x8ee20148, 0x24420001, 0xaee20148, 0x8002287, 
-0x8ee20148, 0x3c020900, 0xaee05228, 0xaee0522c, 0xaee05230, 0xaee05234, 
-0xaee001c8, 0x3c010001, 0x370821, 0xa02083a1, 0xafa20018, 0x8ee205f8, 
-0x8f430228, 0x24420001, 0x304a00ff, 0x514300f7, 0xafa00010, 0x8ee205f8, 
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 
+0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 
+0x8001d70, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 
+0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 0xac650004, 
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24070001, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144a001f, 
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10480007, 
+0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8001d5d, 
+0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
+0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x8001d70, 
+0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 
+0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, 
+0x0, 0x3c040001, 0x24844750, 0xafa00010, 0xafa00014, 0x8f860120, 
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001d9c, 0x0, 
+0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 
+0xc002403, 0x34a5f010, 0x8001d9c, 0x0, 0x3c040001, 0x24844768, 
+0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 
+0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20124, 0x24420001, 
+0xaee20124, 0x8001f93, 0x8ee20124, 0x27440212, 0xc0022f8, 0x24050006, 
+0x3049001f, 0x928c0, 0x2e51021, 0x9442726c, 0x30428000, 0x1040002f, 
+0x2e51021, 0x9442726c, 0x30424000, 0x1440001c, 0xb71021, 0x9443726e, 
+0x97420212, 0x14620018, 0xb71021, 0x8c437270, 0x8f420214, 0x54620016, 
+0xafa20010, 0x92e204c8, 0x10400007, 0x24020001, 0x8ee304cc, 0x1221004, 
+0x21027, 0x621824, 0x8001dc5, 0xaee304cc, 0x8f830228, 0x1221004, 
+0x21027, 0x621824, 0xaf830228, 0x910c0, 0x2e21821, 0x3402c000, 
+0x8001e4a, 0xa462726c, 0x8f420214, 0xafa20010, 0x910c0, 0x571021, 
+0x8c42726c, 0x3c040001, 0x24844774, 0x3c050003, 0xafa20014, 0x8f470210, 
+0x34a5f01c, 0xc002403, 0x1203021, 0x8001e7f, 0x3c020800, 0xb71021, 
+0x9443726e, 0x97420212, 0x14620019, 0x918c0, 0xb71021, 0x8c437270, 
+0x8f420214, 0x14620014, 0x918c0, 0x2e51021, 0x9447726c, 0x720c0, 
+0x971021, 0x9443736e, 0xb71021, 0xa443726e, 0x971021, 0x8c437370, 
+0xb71021, 0xac437270, 0x2e41021, 0x9443736c, 0x2e51021, 0xa443726c, 
+0x2e41821, 0x3402c000, 0x8001e4a, 0xa462736c, 0x2e31021, 0x9447726c, 
+0x3021, 0x720c0, 0x2e41021, 0x9442736c, 0x4021, 0x30428000, 
+0x14400025, 0xe02821, 0x605021, 0x340bc000, 0x971021, 0x9443736e, 
+0x97420212, 0x54620015, 0xe02821, 0x971021, 0x8c437370, 0x8f420214, 
+0x54620010, 0xe02821, 0x11000006, 0x2e41021, 0x9443736c, 0x510c0, 
+0x2e21021, 0x8001e16, 0xa443736c, 0x9443736c, 0x2ea1021, 0xa443726c, 
+0x710c0, 0x2e21021, 0xa44b736c, 0x8001e24, 0x24060001, 0x510c0, 
+0x2e21021, 0x9447736c, 0x720c0, 0x2e41021, 0x9442736c, 0x30428000, 
+0x1040ffdf, 0x25080001, 0x30c200ff, 0x14400025, 0x2021, 0x720c0, 
+0x971021, 0x9443736e, 0x97420212, 0x1462000f, 0x910c0, 0x971021, 
+0x8c437370, 0x8f420214, 0x1462000a, 0x910c0, 0x2e41821, 0x3402c000, 
+0x15000015, 0xa462736c, 0x910c0, 0x2e21821, 0x34028000, 0x8001e4a, 
+0xa462726c, 0x571021, 0x8c42726c, 0x3c040001, 0x24844780, 0x3c050003, 
+0xafa20010, 0x710c0, 0x571021, 0x8c42736c, 0x34a5001e, 0x1203021, 
+0xc002403, 0xafa20014, 0x8001e7f, 0x3c020800, 0x2021, 0x428c0, 
+0xb71021, 0x9443776e, 0x97420212, 0x5462002b, 0x24840001, 0xb71021, 
+0x8c437770, 0x8f420214, 0x54620026, 0x24840001, 0x3c020001, 0x571021, 
+0x8c4283a4, 0x2442ffff, 0x3c010001, 0x370821, 0xac2283a4, 0x3c020001, 
+0x571021, 0x8c4283a4, 0x809021, 0x242102b, 0x1040000e, 0x24b1776c, 
+0x24b07774, 0x2f02021, 0x2f12821, 0xc002490, 0x24060008, 0x26310008, 
+0x3c020001, 0x571021, 0x8c4283a4, 0x26520001, 0x242102b, 0x1440fff5, 
+0x26100008, 0x3c040001, 0x972021, 0x8c8483a4, 0x24050008, 0x420c0, 
+0x2484776c, 0xc002488, 0x2e42021, 0x8001e7f, 0x3c020800, 0x2c820080, 
+0x1440ffcf, 0x428c0, 0x3c020800, 0x34422000, 0xafa20018, 0x8ee205f8, 
+0x8f430228, 0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 0x8ee205f8, 
 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 
-0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x10400067, 
+0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 
 0x5821, 0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 
 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 
-0x8f820128, 0x15020007, 0x1021, 0x8ee201a0, 0x3821, 0x24420001, 
-0xaee201a0, 0x80020d4, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 
-0x8ee40430, 0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
-0xace40000, 0xace50004, 0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 
-0x210c0, 0x244205fc, 0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 
-0xaf880120, 0x92e24e10, 0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 
-0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 
-0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10620005, 0x0, 0x80020c1, 0x0, 0x14600005, 
-0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400010, 0xac800000, 0x80020d4, 0x0, 0x8ee24e20, 
-0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 
-0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 
-0x0, 0x316300ff, 0x24020001, 0x54620075, 0xafa00010, 0xaeea05f8, 
-0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 
-0x5821, 0x240e0008, 0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, 
-0xaee201a0, 0x800213d, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
+0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 
+0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8001ef7, 0x8ee201a0, 
+0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 
+0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 
+0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 
+0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
+0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
+0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
+0x8001ee4, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 
+0x8001ef7, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 0x8f820054, 
+0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 
+0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 
+0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240e0008, 0x240d0011, 
+0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, 
+0xaee201a0, 0x8001f63, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 0xac640000, 
 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 
 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
 0x10480007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
-0x800212a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0x8001f50, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 
-0x800213d, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 
+0x8001f63, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 0x1021, 
 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 
-0x1221023, 0x2c420033, 0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 
-0x10620022, 0x0, 0x3c040001, 0x24844540, 0xafa00010, 0xafa00014, 
-0x8f860120, 0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f011, 0x8002169, 
-0x0, 0x3c040001, 0x2484454c, 0xafa00014, 0x8f860120, 0x8f870124, 
-0x3c050009, 0xc0023a7, 0x34a5f010, 0x8002169, 0x0, 0x3c040001, 
-0x24844558, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 
-0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20120, 
-0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20164, 0x24420001, 0xaee20164, 
-0x8002287, 0x8ee20164, 0x8f42025c, 0x26e40094, 0xaee20060, 0x8f420260, 
-0x27450200, 0x24060008, 0xc00243e, 0xaee20068, 0x8f820220, 0x30420008, 
-0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001, 
-0xaee2011c, 0x8002287, 0x8ee2011c, 0x3c040001, 0x2484459c, 0xafa00010, 
-0xafa00014, 0x8fa60020, 0x3c050003, 0xc0023a7, 0x34a5f00f, 0x93a20020, 
-0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee205f8, 0x8f430228, 
-0x24420001, 0x304900ff, 0x512300dc, 0xafa00010, 0x8ee205f8, 0x210c0, 
-0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f870120, 
-0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 
-0x15020007, 0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 
-0x80021ff, 0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 
-0x8ee50434, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 
-0xace50004, 0x8ee305f8, 0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 
-0xace9001c, 0x318c0, 0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 
-0xace20010, 0xaf880120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80021e9, 
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80021ff, 
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54e0000c, 
-0xaee905f8, 0x3c040001, 0x248445a4, 0xafa00010, 0xafa00014, 0x8ee605f8, 
-0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f000, 0x800227f, 0x0, 
-0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
-0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 0x24420001, 
-0xaee201a0, 0x8002263, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
-0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
-0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
+0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 
+0x10620022, 0x0, 0x3c040001, 0x24844750, 0xafa00010, 0xafa00014, 
+0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001f8f, 
+0x0, 0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 0x8f870124, 
+0x3c050009, 0xc002403, 0x34a5f010, 0x8001f8f, 0x0, 0x3c040001, 
+0x24844768, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 
+0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20128, 
+0x24420001, 0xaee20128, 0x8ee20128, 0x8ee20160, 0x24420001, 0xaee20160, 
+0x80022e2, 0x8ee20160, 0x8fa20020, 0x21200, 0x21d02, 0x24020001, 
+0x10620005, 0x24020002, 0x1062000d, 0x0, 0x8001fb3, 0xafa00010, 
+0x92e204c8, 0x14400006, 0x24020001, 0x8f820228, 0xaee204cc, 0x2402ffff, 
+0xaf820228, 0x24020001, 0x8001fba, 0xa2e204c8, 0x92e204c8, 0x5040000c, 
+0xa2e004c8, 0x8ee204cc, 0xaf820228, 0x8001fba, 0xa2e004c8, 0x3c040001, 
+0x24844788, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f009, 
+0x8ee2013c, 0x24420001, 0xaee2013c, 0x80022e2, 0x8ee2013c, 0x8fa20020, 
+0x21200, 0x22502, 0x24020001, 0x10820005, 0x24020002, 0x1082000f, 
+0x0, 0x8001fdf, 0xafa00010, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
+0x431024, 0x34420008, 0xaf820220, 0x24020001, 0x3c010001, 0x370821, 
+0xa02283a2, 0x8001fe6, 0xaee40108, 0x8f820220, 0x3c0308ff, 0x3463fff7, 
+0x431024, 0xaf820220, 0x3c010001, 0x370821, 0xa02083a2, 0x8001fe6, 
+0xaee40108, 0x3c040001, 0x24844794, 0xafa00014, 0x8fa60020, 0x3c050003, 
+0xc002403, 0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c, 0x80022e2, 
+0x8ee2012c, 0x8fa20020, 0x21200, 0x21d02, 0x24020001, 0x10620005, 
+0x24020002, 0x1062000e, 0x0, 0x800200d, 0xafa00010, 0x8f820220, 
+0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001, 
+0x3c010001, 0x370821, 0x8002014, 0xa02283a3, 0x3c020001, 0x571021, 
+0x904283a2, 0x3c010001, 0x370821, 0x1440000e, 0xa02083a3, 0x8f820220, 
+0x3c0308ff, 0x3463fff7, 0x431024, 0x8002014, 0xaf820220, 0x3c040001, 
+0x248447a0, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00b, 
+0x8ee20114, 0x24420001, 0xaee20114, 0x80022e2, 0x8ee20114, 0x27840208, 
+0x27450200, 0xc00249a, 0x24060008, 0x26e40094, 0x27450200, 0xc00249a, 
+0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, 0x80022e2, 0x8ee20134, 
+0x8f460248, 0x24040001, 0xc004eac, 0x24050004, 0x8ee20130, 0x24420001, 
+0xaee20130, 0x80022e2, 0x8ee20130, 0x8ef301c4, 0x8ef401c8, 0x8ef501cc, 
+0x8ee20140, 0x26e40030, 0x24420001, 0xaee20140, 0x8ef00140, 0x8ef10074, 
+0x8ef20070, 0xc002488, 0x24050400, 0xaef301c4, 0xaef401c8, 0xaef501cc, 
+0xaef00140, 0xaef10074, 0xaef20070, 0x8f42025c, 0x26e40094, 0xaee20060, 
+0x8f420260, 0x27450200, 0x24060008, 0xaee20068, 0x24020006, 0xc00249a, 
+0xaee20064, 0x3c023b9a, 0x3442ca00, 0xaee2006c, 0x240203e8, 0x24040002, 
+0x24030001, 0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220, 0x30420008, 
+0x10400004, 0x0, 0xaee30108, 0x800205d, 0x2021, 0xaee40108, 
+0x2021, 0x3c030001, 0x641821, 0x90634f60, 0x2e41021, 0x24840001, 
+0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, 
+0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, 0x80022e2, 
+0xa040009c, 0x240a0400, 0x24090040, 0x24080001, 0x8f830100, 0x27623000, 
+0x24660020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 
+0x0, 0x8f820104, 0x14c20007, 0x26e20030, 0x8ee201a4, 0x3821, 
+0x24420001, 0xaee201a4, 0x800209f, 0x8ee201a4, 0x8ee404a8, 0x8ee504ac, 
+0xac620008, 0xa46a000e, 0xac600018, 0xac60001c, 0xac640000, 0xac650004, 
+0x8ee204bc, 0xac620010, 0xaf860100, 0x92e204dc, 0x1440000e, 0x24070001, 
+0x8ee24e18, 0x24420001, 0x50490003, 0x1021, 0x8ee24e18, 0x24420001, 
+0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21021, 0xac400000, 
+0xac480004, 0x10e0ffd2, 0x0, 0x8ee20148, 0x24420001, 0xaee20148, 
+0x80022e2, 0x8ee20148, 0x3c020900, 0xaee05228, 0xaee0522c, 0xaee05230, 
+0xaee05234, 0xaee001c8, 0x3c010001, 0x370821, 0xa02083a1, 0xafa20018, 
+0x8ee205f8, 0x8f430228, 0x24420001, 0x304a00ff, 0x514300fd, 0xafa00010, 
+0x8ee205f8, 0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 
+0xac440600, 0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 
+0x1040006a, 0x5821, 0x24100008, 0x240f000d, 0x240d0007, 0x240c0040, 
+0x240e0001, 0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 
+0x27683000, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 
+0x1021, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8002126, 
+0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 
+0x8ee205f8, 0xa4f0000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 
+0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 
+0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
+0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
+0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
+0x0, 0x8002113, 0x0, 0x14600005, 0x0, 0x8f820128, 
+0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
+0xac800000, 0x8002126, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54e00006, 0x240b0001, 
+0x8f820054, 0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 
+0x24020001, 0x54620078, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 
+0x24690032, 0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240e0008, 
+0x240d0011, 0x240a0012, 0x24080040, 0x240c0001, 0x8f830120, 0x27623800, 
+0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 
+0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 
+0x24420001, 0xaee201a0, 0x8002192, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 
+0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0xa46e000e, 0xac6d0018, 
+0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 
+0x14400033, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c820000, 0x144a001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
+0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
+0x24420001, 0x10480007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
+0x0, 0x800217f, 0x0, 0x14600005, 0x0, 0x8f820128, 
+0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
+0xac800000, 0x8002192, 0x0, 0x8ee24e20, 0x24420001, 0x50480003, 
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 
+0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 
+0x24020001, 0x10620022, 0x0, 0x3c040001, 0x24844750, 0xafa00010, 
+0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 
+0x80021be, 0x0, 0x3c040001, 0x2484475c, 0xafa00014, 0x8f860120, 
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80021be, 0x0, 
+0x3c040001, 0x24844768, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
+0xc002403, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 
+0x8ee20120, 0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20164, 0x24420001, 
+0xaee20164, 0x80022e2, 0x8ee20164, 0x8f42025c, 0x26e40094, 0xaee20060, 
+0x8f420260, 0x27450200, 0x24060008, 0xc00249a, 0xaee20068, 0x8f820220, 
+0x30420008, 0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, 
+0x24420001, 0xaee2011c, 0x80022e2, 0x8ee2011c, 0x3c040001, 0x248447ac, 
+0xafa00010, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00f, 
+0x93a20020, 0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee205f8, 
+0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, 0x8ee205f8, 
+0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 
+0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 
+0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 
+0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8002257, 0x8ee201a0, 
+0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee305f8, 
+0x24020008, 0xa4e2000e, 0x2402000d, 0xace20018, 0xace9001c, 0x318c0, 
+0x246305fc, 0x2e31021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 
 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 
+0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 
 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 0x8ee24e24, 
-0x24420001, 0x10a20005, 0x0, 0x800224d, 0x0, 0x14a00005, 
+0x24420001, 0x10a20005, 0x0, 0x8002241, 0x0, 0x14a00005, 
 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
-0x2c420011, 0x50400013, 0xac800000, 0x8002263, 0x0, 0x8ee24e20, 
+0x2c420011, 0x50400013, 0xac800000, 0x8002257, 0x0, 0x8ee24e20, 
 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 
-0xac820000, 0x24020001, 0xac820004, 0x14e0001b, 0x0, 0x3c040001, 
-0x248445ac, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
-0xc0023a7, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x800227f, 
-0x8ee201ac, 0x3c040001, 0x248445b8, 0xafa00014, 0x8ee605f8, 0x8f470228, 
-0x3c050009, 0xc0023a7, 0x34a5f005, 0x8ee201a8, 0x24420001, 0xaee201a8, 
-0x8ee201a8, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x8ee2014c, 0x8ee2015c, 
-0x24420001, 0xaee2015c, 0x8ee2015c, 0x8f43022c, 0x8f42010c, 0x14620009, 
-0x24020002, 0xaf820064, 0x8f820064, 0x14400005, 0x0, 0x8f43022c, 
-0x8f42010c, 0x1462f897, 0x0, 0x8fbf0044, 0x8fb60040, 0x8fb5003c, 
-0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 0x3e00008, 
-0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8, 
-0x354a8320, 0x90870000, 0x24840001, 0x3021, 0x1071026, 0x30420001, 
-0x10400002, 0x81842, 0x6a1826, 0x604021, 0x24c60001, 0x2cc20008, 
-0x1440fff7, 0x73842, 0x25290001, 0x125102b, 0x1440fff0, 0x0, 
-0x1001021, 0x3e00008, 0x27bd0008, 0x0, 0x27bdffe8, 0x27642800, 
-0xafbf0010, 0xc00242c, 0x24051000, 0x24020021, 0xaf800100, 0xaf800104, 
-0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118, 0xaf800120, 0xaf800124, 
-0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138, 0xaee04e18, 0xaee04e1c, 
-0xaee04e20, 0xaee04e24, 0xaf82011c, 0x8f420218, 0x30420040, 0x10400004, 
-0x0, 0x8f82011c, 0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 
-0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010, 0x8f820100, 
-0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, 0x3c040001, 0x2484466c, 
-0xc0023a7, 0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824, 0x3c020400, 
-0x1062002b, 0x43102b, 0x14400008, 0x3c022000, 0x3c020100, 0x10620026, 
-0x3c020200, 0x10620013, 0x0, 0x8002316, 0x0, 0x1062000a, 
-0x43102b, 0x1040001e, 0x3c024000, 0x1462001c, 0x0, 0x8ee2018c, 
-0x24420001, 0xaee2018c, 0x8002316, 0x8ee2018c, 0x8ee20188, 0x24420001, 
-0xaee20188, 0x8002316, 0x8ee20188, 0x8f82011c, 0x34420002, 0xaf82011c, 
-0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f82011c, 
-0x2403fffd, 0x431024, 0xaf82011c, 0x8ee2019c, 0x24420001, 0xaee2019c, 
-0x8002319, 0x8ee2019c, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, 
-0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820120, 
-0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, 0x8f8600a0, 0x8f87011c, 
-0x3c040001, 0x24844678, 0xc0023a7, 0x34a5f000, 0x8f8300a0, 0x3c027f00, 
-0x621824, 0x3c020400, 0x10620055, 0x8021, 0x43102b, 0x14400008, 
-0x3c042000, 0x3c020100, 0x1062004f, 0x3c020200, 0x1062003c, 0x0, 
-0x8002384, 0x0, 0x10640005, 0x83102b, 0x10400047, 0x3c024000, 
-0x14620045, 0x0, 0x8f8200a0, 0x441024, 0x10400006, 0x0, 
-0x8ee20190, 0x24420001, 0xaee20190, 0x800234d, 0x8ee20190, 0x8ee20194, 
-0x24420001, 0xaee20194, 0x8ee20194, 0x8f82011c, 0x34420002, 0xaf82011c, 
-0x8f82011c, 0x30420200, 0x1040001b, 0x0, 0x8f8300a0, 0x8f840124, 
-0x8f8200ac, 0x14400007, 0x24020001, 0x3c020001, 0x3442f000, 0x621024, 
-0x50400001, 0x24100001, 0x24020001, 0x1200000d, 0xaf8200a0, 0x8f820124, 
-0x2442ffe0, 0xaf820124, 0x8f820124, 0x8f820124, 0x27633000, 0x43102b, 
-0x10400005, 0x276237e0, 0xaf820124, 0x800236e, 0x0, 0xaf840124, 
-0x8f82011c, 0x2403fffd, 0x431024, 0x8002387, 0xaf82011c, 0x8f82011c, 
-0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 
-0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee20198, 
-0x24420001, 0xaee20198, 0x8002387, 0x8ee20198, 0x8f8200a0, 0x34420001, 
-0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x0, 
-0x3c020001, 0x8c424d78, 0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb00010, 
-0x3c100001, 0x26104eb0, 0x2002021, 0xc00242c, 0x24052000, 0x26021fe0, 
-0x3c010001, 0xac224e84, 0x3c010001, 0xac224e80, 0xaf420250, 0x24022000, 
-0xaf500254, 0xaf420258, 0x24020001, 0x3c010001, 0xac224d78, 0x8fbf0014, 
-0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c030001, 0x8c634e84, 0x8c820000, 
-0x8fa80010, 0x8fa90014, 0xac620000, 0x3c020001, 0x8c424e84, 0x8c830004, 
-0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, 
-0xac480018, 0xac49001c, 0x3c010001, 0xac234e84, 0xac44000c, 0x3c020001, 
-0x24424eb0, 0x62182b, 0x10600005, 0x0, 0x3c020001, 0x8c424e80, 
-0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 
-0xac620000, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 0xac620004, 
-0x3e00008, 0xaf430250, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 
-0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, 0x808021, 0xafb50024, 
-0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, 0xafbf0028, 0xafb3001c, 
-0xafb20018, 0xac620000, 0x3c050001, 0x8ca54e84, 0x3c020001, 0x8c424d60, 
-0xc09021, 0xe09821, 0x10800006, 0xaca20004, 0x24a50008, 0xc002434, 
-0x24060018, 0x80023f2, 0x0, 0x24a40008, 0xc00242c, 0x24050018, 
-0x3c020001, 0x8c424e84, 0x3c050001, 0x24a54eb0, 0x2442ffe0, 0x3c010001, 
-0xac224e84, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c424e80, 
-0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x8e020000, 0xac620000, 
-0x3c030001, 0x8c634e84, 0x8e020004, 0xac620004, 0xac710008, 0x8f840054, 
-0x2462ffe0, 0x3c010001, 0xac224e84, 0x45102b, 0xac720010, 0xac730014, 
-0xac740018, 0xac75001c, 0x10400005, 0xac64000c, 0x3c020001, 0x8c424e80, 
-0x3c010001, 0xac224e84, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 
-0xac620000, 0x3c030001, 0x8c634e84, 0x3c020001, 0x8c424d60, 0xac620004, 
-0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 
-0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005, 0x0, 
-0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 0x3e00008, 0x0, 
-0x10c00007, 0x0, 0x8c820000, 0x24840004, 0x24c6fffc, 0xaca20000, 
-0x14c0fffb, 0x24a50004, 0x3e00008, 0x0, 0x10c00007, 0x0, 
-0x8ca20000, 0x24a50004, 0x24c6fffc, 0xac820000, 0x14c0fffb, 0x24840004, 
-0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0020, 
-0x8ee304d4, 0x8ee204d0, 0x1062041e, 0x0, 0x8ee204d4, 0x8ee304ec, 
-0x21100, 0x626021, 0x95870008, 0x8d8a0000, 0x8d8b0004, 0x958d000a, 
-0x8ee2724c, 0x8ee3725c, 0x30e4ffff, 0x441021, 0x62182b, 0x10600015, 
-0x31a20004, 0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 0x8ee2725c, 
-0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, 0x8ee2724c, 0x8ee3725c, 
-0x441021, 0x62182b, 0x10600006, 0x31a20004, 0x8ee201b4, 0x24420001, 
-0xaee201b4, 0x800286d, 0x8ee201b4, 0x10400234, 0x31a20200, 0x10400144, 
-0x4821, 0x96e2045a, 0x30420010, 0x10400140, 0x0, 0x8f840100, 
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 
+0xac820000, 0x24020001, 0xac820004, 0x54e0000c, 0xaee905f8, 0x3c040001, 
+0x248447b4, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
+0xc002403, 0x34a5f000, 0x80022da, 0x0, 0x8f830120, 0x27623800, 
+0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 
+0x0, 0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x3821, 
+0x24420001, 0xaee201a0, 0x80022be, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 
+0x8ee40490, 0x8ee50494, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 
+0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 
+0xaf860120, 0x92e24e10, 0x14400037, 0x24070001, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 
+0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 0x0, 
+0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x80022a8, 0x0, 
+0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80022be, 0x0, 
+0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e20, 
+0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14e0001b, 0x0, 
+0x3c040001, 0x248447bc, 0xafa00010, 0xafa00014, 0x8ee605f8, 0x8f470228, 
+0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201ac, 0x24420001, 0xaee201ac, 
+0x80022da, 0x8ee201ac, 0x3c040001, 0x248447c8, 0xafa00014, 0x8ee605f8, 
+0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201a8, 0x24420001, 
+0xaee201a8, 0x8ee201a8, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x8ee2014c, 
+0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, 0x8f43022c, 0x8f42010c, 
+0x14620009, 0x24020002, 0xaf820064, 0x8f820064, 0x14400005, 0x0, 
+0x8f43022c, 0x8f42010c, 0x1462f877, 0x0, 0x8fbf0044, 0x8fb60040, 
+0x8fb5003c, 0x8fb40038, 0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, 
+0x3e00008, 0x27bd0048, 0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, 
+0x3c0aedb8, 0x354a8320, 0x90870000, 0x24840001, 0x3021, 0x1071026, 
+0x30420001, 0x10400002, 0x81842, 0x6a1826, 0x604021, 0x24c60001, 
+0x2cc20008, 0x1440fff7, 0x73842, 0x25290001, 0x125102b, 0x1440fff0, 
+0x0, 0x1001021, 0x3e00008, 0x27bd0008, 0x0, 0x0, 
+0x27bdffe8, 0x27642800, 0xafbf0010, 0xc002488, 0x24051000, 0x24020021, 
+0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 0xaf800118, 
+0xaf800120, 0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134, 0xaf800138, 
+0xaee04e18, 0xaee04e1c, 0xaee04e20, 0xaee04e24, 0xaf82011c, 0x8f420218, 
+0x30420040, 0x10400004, 0x0, 0x8f82011c, 0x34420004, 0xaf82011c, 
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, 
+0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, 
+0x3c040001, 0x2484487c, 0xc002403, 0x34a5f000, 0x8f8300b0, 0x3c027f00, 
+0x621824, 0x3c020400, 0x1062002b, 0x43102b, 0x14400008, 0x3c022000, 
+0x3c020100, 0x10620026, 0x3c020200, 0x10620013, 0x0, 0x8002372, 
+0x0, 0x1062000a, 0x43102b, 0x1040001e, 0x3c024000, 0x1462001c, 
+0x0, 0x8ee2018c, 0x24420001, 0xaee2018c, 0x8002372, 0x8ee2018c, 
+0x8ee20188, 0x24420001, 0xaee20188, 0x8002372, 0x8ee20188, 0x8f82011c, 
+0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 
+0xaf830104, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee2019c, 
+0x24420001, 0xaee2019c, 0x8002375, 0x8ee2019c, 0x8f8200b0, 0x34420001, 
+0xaf8200b0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf001c, 
+0xafb00018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, 
+0x8f8600a0, 0x8f87011c, 0x3c040001, 0x24844888, 0xc002403, 0x34a5f000, 
+0x8f8300a0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620055, 0x8021, 
+0x43102b, 0x14400008, 0x3c042000, 0x3c020100, 0x1062004f, 0x3c020200, 
+0x1062003c, 0x0, 0x80023e0, 0x0, 0x10640005, 0x83102b, 
+0x10400047, 0x3c024000, 0x14620045, 0x0, 0x8f8200a0, 0x441024, 
+0x10400006, 0x0, 0x8ee20190, 0x24420001, 0xaee20190, 0x80023a9, 
+0x8ee20190, 0x8ee20194, 0x24420001, 0xaee20194, 0x8ee20194, 0x8f82011c, 
+0x34420002, 0xaf82011c, 0x8f82011c, 0x30420200, 0x1040001b, 0x0, 
+0x8f8300a0, 0x8f840124, 0x8f8200ac, 0x14400007, 0x24020001, 0x3c020001, 
+0x3442f000, 0x621024, 0x50400001, 0x24100001, 0x24020001, 0x1200000d, 
+0xaf8200a0, 0x8f820124, 0x2442ffe0, 0xaf820124, 0x8f820124, 0x8f820124, 
+0x27633000, 0x43102b, 0x10400005, 0x276237e0, 0xaf820124, 0x80023ca, 
+0x0, 0xaf840124, 0x8f82011c, 0x2403fffd, 0x431024, 0x80023e3, 
+0xaf82011c, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 
+0x34420001, 0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 
+0xaf82011c, 0x8ee20198, 0x24420001, 0xaee20198, 0x80023e3, 0x8ee20198, 
+0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, 
+0x27bd0020, 0x0, 0x3c020001, 0x8c424f88, 0x27bdffe8, 0xafbf0014, 
+0x14400012, 0xafb00010, 0x3c100001, 0x261050c0, 0x2002021, 0xc002488, 
+0x24052000, 0x26021fe0, 0x3c010001, 0xac225094, 0x3c010001, 0xac225090, 
+0xaf420250, 0x24022000, 0xaf500254, 0xaf420258, 0x24020001, 0x3c010001, 
+0xac224f88, 0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 0x3c030001, 
+0x8c635094, 0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000, 0x3c020001, 
+0x8c425094, 0x8c830004, 0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 
+0xac460010, 0xac470014, 0xac480018, 0xac49001c, 0x3c010001, 0xac235094, 
+0xac44000c, 0x3c020001, 0x244250c0, 0x62182b, 0x10600005, 0x0, 
+0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094, 
+0x3c020001, 0x8c424f70, 0xac620000, 0x3c030001, 0x8c635094, 0x3c020001, 
+0x8c424f70, 0xac620004, 0x3e00008, 0xaf430250, 0x3c030001, 0x8c635094, 
+0x3c020001, 0x8c424f70, 0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, 
+0x808021, 0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, 
+0xafbf0028, 0xafb3001c, 0xafb20018, 0xac620000, 0x3c050001, 0x8ca55094, 
+0x3c020001, 0x8c424f70, 0xc09021, 0xe09821, 0x10800006, 0xaca20004, 
+0x24a50008, 0xc002490, 0x24060018, 0x800244e, 0x0, 0x24a40008, 
+0xc002488, 0x24050018, 0x3c020001, 0x8c425094, 0x3c050001, 0x24a550c0, 
+0x2442ffe0, 0x3c010001, 0xac225094, 0x45102b, 0x10400005, 0x0, 
+0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094, 
+0x8e020000, 0xac620000, 0x3c030001, 0x8c635094, 0x8e020004, 0xac620004, 
+0xac710008, 0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225094, 0x45102b, 
+0xac720010, 0xac730014, 0xac740018, 0xac75001c, 0x10400005, 0xac64000c, 
+0x3c020001, 0x8c425090, 0x3c010001, 0xac225094, 0x3c030001, 0x8c635094, 
+0x3c020001, 0x8c424f70, 0xac620000, 0x3c030001, 0x8c635094, 0x3c020001, 
+0x8c424f70, 0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, 
+0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 
+0x10a00005, 0x0, 0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 
+0x3e00008, 0x0, 0x10c00007, 0x0, 0x8c820000, 0x24840004, 
+0x24c6fffc, 0xaca20000, 0x14c0fffb, 0x24a50004, 0x3e00008, 0x0, 
+0x10c00007, 0x0, 0x8ca20000, 0x24a50004, 0x24c6fffc, 0xac820000, 
+0x14c0fffb, 0x24840004, 0x3e00008, 0x0, 0x3e00008, 0x0, 
+0x27bdffd8, 0xafbf0020, 0x8ee304d4, 0x8ee204d0, 0x10620436, 0x0, 
+0x8ee204d4, 0x8ee304ec, 0x21100, 0x626021, 0x95870008, 0x8d8a0000, 
+0x8d8b0004, 0x958d000a, 0x8ee2724c, 0x8ee3725c, 0x30e4ffff, 0x441021, 
+0x62182b, 0x10600015, 0x31a20004, 0x8f8200d8, 0x8ee37248, 0x431023, 
+0xaee2725c, 0x8ee2725c, 0x1c400003, 0x3c030001, 0x431021, 0xaee2725c, 
+0x8ee2724c, 0x8ee3725c, 0x441021, 0x62182b, 0x10600006, 0x31a20004, 
+0x8ee201b4, 0x24420001, 0xaee201b4, 0x80028e1, 0x8ee201b4, 0x10400240, 
+0x31a20200, 0x1040014d, 0x4821, 0x96e2045a, 0x30420010, 0x10400149, 
+0x0, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 
+0x27652800, 0x8f820108, 0x10a20004, 0x0, 0x8f820104, 0x14a20006, 
+0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x800252c, 0x8ee201a4, 
+0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 0xa482000e, 0xac860018, 
+0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 0xac820010, 0xaf850100, 
+0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 
+0x2e22021, 0x8c820000, 0x1446001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 
+0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 
+0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 
+0x10a20005, 0x0, 0x8002516, 0x0, 0x14a00005, 0x0, 
+0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 
+0x50400013, 0xac800000, 0x800252c, 0x0, 0x8ee24e18, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 
+0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 
+0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, 0x8ee27254, 
+0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 
+0x34a5f114, 0x8ee27254, 0x34843800, 0x3641821, 0x24420010, 0x43102b, 
+0x14400073, 0x0, 0x8ee27254, 0x24480010, 0x3641021, 0x102102b, 
+0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000, 0x24a60020, 
+0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 0x0, 
+0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 
+0xaee201a4, 0x80025a0, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 
+0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, 
+0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 
+0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 
+0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 
+0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 
+0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 
+0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x800258a, 0x0, 
+0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x80025a0, 0x0, 
+0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 
+0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 
+0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 
+0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 
+0x8ee604d4, 0x80028be, 0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, 
+0x800261d, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 
+0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 0x0, 0x8f820104, 
+0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 
+0x800260d, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004, 
+0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018, 0x24630010, 
+0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 
+0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 
+0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 
+0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 
+0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x80025f7, 
+0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 
+0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800260d, 
+0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
+0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 
+0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 
+0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 
+0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f015, 0x8ee37254, 0xa462000c, 
+0x8ee37254, 0x9582000e, 0xa462000e, 0x8002681, 0x24e70004, 0x8f840100, 
 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 
-0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x80024cd, 
-0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 0xa482000e, 
-0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 0xac820010, 
-0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 
-0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 0x0, 0x8ee34e18, 
+0x10a20004, 0x0, 0x8f820104, 0x14a20007, 0x24020006, 0x8ee201a4, 
+0x4821, 0x24420001, 0xaee201a4, 0x8002677, 0x8ee201a4, 0xac8a0000, 
+0xac8b0004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 0x8ee204d4, 
+0xac82001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xac820010, 0xaf850100, 
+0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 
+0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 
 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 
-0x24420001, 0x10a20005, 0x0, 0x80024b7, 0x0, 0x14a00005, 
+0x24420001, 0x10a20005, 0x0, 0x8002661, 0x0, 0x14a00005, 
 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 
-0x2c420011, 0x50400013, 0xac800000, 0x80024cd, 0x0, 0x8ee24e18, 
+0x2c420011, 0x50400013, 0xac800000, 0x8002677, 0x0, 0x8ee24e18, 
 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 
 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 
-0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, 
-0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 
-0x800284a, 0x34a5f114, 0x8ee27254, 0x34843800, 0x3641821, 0x24420010, 
-0x43102b, 0x14400070, 0x0, 0x8ee27254, 0x24480010, 0x3641021, 
-0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 0x27623000, 
-0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x14c20007, 
-0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 0x800253e, 
-0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 0xaca30004, 0x24e2fff4, 
-0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, 0x8ee204d4, 0xaca2001c, 
-0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 
-0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 
-0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 
-0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 
-0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 
-0x10a20005, 0x0, 0x8002528, 0x0, 0x14a00005, 0x0, 
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 
-0x50400013, 0xac800000, 0x800253e, 0x0, 0x8ee24e18, 0x24030040, 
-0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 
-0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 
-0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27254, 
-0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, 
-0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, 0x80025b8, 0xa5020002, 
-0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 
-0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 
-0xaee201a4, 0x80025a8, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 
-0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca20018, 
-0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 
+0xac820000, 0x24020001, 0xac820004, 0x15200009, 0x3c050004, 0xafab0010, 
+0x8ee27254, 0x3c040001, 0x24844af0, 0xafa20014, 0x8ee604d4, 0x80028be, 
+0x34a5f004, 0x8ee2724c, 0x30e7ffff, 0x471021, 0xaee2724c, 0x8ee204d4, 
+0x8ee304ec, 0x8ee47248, 0x21100, 0x431021, 0xac44000c, 0x8ee27248, 
+0xafa20018, 0x8ee3724c, 0xafa3001c, 0x8ee2724c, 0x2c42003c, 0x10400004, 
+0x24620001, 0x2403fffe, 0x431024, 0xafa2001c, 0x8ee27254, 0x3c060001, 
+0x34c63800, 0x8ee3724c, 0x2405fff8, 0x471021, 0x24420007, 0x451024, 
+0x24630007, 0xaee27248, 0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 
+0xaee2725c, 0x3661021, 0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 
+0x431021, 0xaee27248, 0x8ee27248, 0xaee27254, 0x8f8200f0, 0x24470008, 
+0x27621800, 0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 
+0x0, 0x8ee201b0, 0x4821, 0x24420001, 0xaee201b0, 0x80026c4, 
+0x8ee201b0, 0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, 
+0xac440004, 0xaf8700f0, 0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, 
+0x8f8200f4, 0x3c040001, 0x24844afc, 0xafa20014, 0x8fa60018, 0x8fa7001c, 
+0x3c050004, 0xc002403, 0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, 
+0x8ee20088, 0x80028d3, 0xaee0724c, 0x30430003, 0x24020002, 0x10620016, 
+0x28620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x8002703, 
+0x0, 0x24020003, 0x10620017, 0x0, 0x8002703, 0x0, 
+0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 0xaee200e8, 
+0xaee300ec, 0x8ee200e8, 0x8002703, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 
+0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 0xaee300f4, 0x8ee200f0, 
+0x8002703, 0x8ee300f4, 0x8ee200f8, 0x8ee300fc, 0x24630001, 0x2c640001, 
+0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, 0x8ee300fc, 0x8ee2724c, 
+0x8ee400e0, 0x8ee500e4, 0x401821, 0x1021, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xaee400e0, 0xaee500e4, 0x80028d3, 0xaee0724c, 
+0x30e2ffff, 0x104001c1, 0x31a20200, 0x1040014d, 0x4821, 0x96e2045a, 
+0x30420010, 0x10400149, 0x0, 0x8f840100, 0x27623000, 0x24850020, 
+0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a20004, 0x0, 
+0x8f820104, 0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 0xaee201a4, 
+0x800276e, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 0x24060005, 
+0xa482000e, 0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 
+0xac820010, 0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 
+0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 0x0, 
+0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 
+0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 
+0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x8002758, 0x0, 
+0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 
+0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x800276e, 0x0, 
+0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 
+0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 
+0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 
+0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 
+0x8ee604d4, 0x80028be, 0x34a5f014, 0x8ee27254, 0x34843800, 0x3641821, 
+0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27254, 0x24480010, 
+0x3641021, 0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 0x8f850100, 
+0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 
+0x10c20004, 0x0, 0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 
+0x4821, 0x24420001, 0xaee201a4, 0x80027e2, 0x8ee201a4, 0x2c64000c, 
+0x1441021, 0xaca20000, 0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 
+0xaca80008, 0xaca20018, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 
 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 
 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 
 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 
 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 
 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 
-0x8002592, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 
+0x80027cc, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 
 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
-0x80025a8, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 
+0x80027e2, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 
 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 
 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 
-0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 
-0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f015, 0x8ee37254, 
-0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 0x8002619, 0x24e70004, 
-0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 
-0x8f820108, 0x14a20007, 0x24020006, 0x8ee201a4, 0x4821, 0x24420001, 
-0xaee201a4, 0x800260f, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 
-0xa487000e, 0xac820018, 0xac830008, 0x8ee204d4, 0xac82001c, 0x8ee204b8, 
-0x3c030002, 0x431025, 0xac820010, 0xaf850100, 0x92e204dc, 0x14400037, 
+0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27254, 0x3c040001, 0x24844af0, 
+0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f015, 0x34028100, 
+0xa5020000, 0x9582000e, 0x800285f, 0xa5020002, 0x8f850100, 0x27623000, 
+0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 0x8f820108, 0x10c20004, 
+0x0, 0x8f820104, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 
+0x24420001, 0xaee201a4, 0x800284f, 0x8ee201a4, 0x2c64000c, 0x1441021, 
+0xaca20000, 0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 0x24020006, 
+0xaca20018, 0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 0x8ee204b8, 
+0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 0x14400037, 
 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 
 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 
 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 
 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 
-0x0, 0x80025f9, 0x0, 0x14a00005, 0x0, 0x8f820108, 
+0x0, 0x8002839, 0x0, 0x14a00005, 0x0, 0x8f820108, 
 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x800260f, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 
+0xac800000, 0x800284f, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 
 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 
 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 
-0xac820004, 0x15200009, 0x3c050004, 0xafab0010, 0x8ee27254, 0x3c040001, 
-0x248448e0, 0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f004, 0x8ee2724c, 
-0x30e7ffff, 0x471021, 0xaee2724c, 0x8ee204d4, 0x8ee304ec, 0x8ee47248, 
-0x21100, 0x431021, 0xac44000c, 0x8ee27248, 0xafa20018, 0x8ee3724c, 
-0xafa3001c, 0x8ee2724c, 0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 
-0x431024, 0xafa2001c, 0x8ee27254, 0x3c060001, 0x34c63800, 0x8ee3724c, 
-0x2405fff8, 0x471021, 0x24420007, 0x451024, 0x24630007, 0xaee27248, 
-0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 0x3661021, 
-0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 0xaee27248, 
-0x8ee27248, 0xaee27254, 0x8f8200f0, 0x24470008, 0x27621800, 0xe2102b, 
-0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 0x0, 0x8ee201b0, 
-0x4821, 0x24420001, 0xaee201b0, 0x800265c, 0x8ee201b0, 0x8f8200f0, 
-0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, 0xaf8700f0, 
-0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4, 0x3c040001, 
-0x248448ec, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050004, 0xc0023a7, 
-0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088, 0x800285f, 
-0xaee0724c, 0x30430003, 0x24020002, 0x10620016, 0x28620003, 0x10400005, 
-0x24020001, 0x10620008, 0x0, 0x800269b, 0x0, 0x24020003, 
-0x10620017, 0x0, 0x800269b, 0x0, 0x8ee200e8, 0x8ee300ec, 
-0x24630001, 0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 
-0x800269b, 0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 
-0x441021, 0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x800269b, 0x8ee300f4, 
-0x8ee200f8, 0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 
-0xaee300fc, 0x8ee200f8, 0x8ee300fc, 0x8ee2724c, 0x8ee400e0, 0x8ee500e4, 
-0x401821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
-0xaee400e0, 0xaee500e4, 0x800285f, 0xaee0724c, 0x30e2ffff, 0x104001b5, 
-0x31a20200, 0x10400144, 0x4821, 0x96e2045a, 0x30420010, 0x10400140, 
-0x0, 0x8f840100, 0x27623000, 0x24850020, 0xa2102b, 0x50400001, 
-0x27652800, 0x8f820108, 0x14a20006, 0x2402000c, 0x8ee201a4, 0x24420001, 
-0xaee201a4, 0x8002703, 0x8ee201a4, 0xac8a0000, 0xac8b0004, 0x8ee37254, 
-0x24060005, 0xa482000e, 0xac860018, 0xac830008, 0x8ee204d4, 0xac82001c, 
-0x8ee204b8, 0xac820010, 0xaf850100, 0x92e204dc, 0x14400036, 0x24090001, 
-0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 0x1446001f, 
-0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x80026ed, 
-0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 
-0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002703, 
-0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 
-0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 
-0x3c040001, 0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 
-0xafa20014, 0x8ee604d4, 0x800284a, 0x34a5f014, 0x8ee27254, 0x34843800, 
-0x3641821, 0x24420010, 0x43102b, 0x14400070, 0x0, 0x8ee27254, 
-0x24480010, 0x3641021, 0x102102b, 0x14400002, 0x3c02ffff, 0x1024021, 
-0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, 0x27662800, 
-0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 0x4821, 0x24420001, 
-0xaee201a4, 0x8002774, 0x8ee201a4, 0x2c64000c, 0x1441021, 0xaca20000, 
-0xaca30004, 0x24e2fff4, 0xa4a2000e, 0x24020006, 0xaca80008, 0xaca20018, 
-0x8ee204d4, 0xaca2001c, 0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 
-0xaf860100, 0x92e204dc, 0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 
-0x24424e28, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 
-0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 
-0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 
-0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 0x800275e, 0x0, 
-0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 
-0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002774, 0x0, 
-0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 
-0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 
-0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 
-0xafab0010, 0x8ee27254, 0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 
-0x8ee604d4, 0x800284a, 0x34a5f015, 0x34028100, 0xa5020000, 0x9582000e, 
-0x80027ee, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 
-0x50400001, 0x27662800, 0x8f820108, 0x14c20007, 0x2563000c, 0x8ee201a4, 
-0x4821, 0x24420001, 0xaee201a4, 0x80027de, 0x8ee201a4, 0x2c64000c, 
-0x1441021, 0xaca20000, 0xaca30004, 0x8ee37254, 0x24e2fff4, 0xa4a2000e, 
-0x24020006, 0xaca20018, 0x24630010, 0xaca30008, 0x8ee204d4, 0xaca2001c, 
-0x8ee204b8, 0x3c030002, 0x431025, 0xaca20010, 0xaf860100, 0x92e204dc, 
-0x14400037, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 
-0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 
+0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 0x3c040001, 
+0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80028be, 0x34a5f016, 
+0x8ee37254, 0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 0x80028c2, 
+0x24e70004, 0x8f830100, 0x27623000, 0x24640020, 0x82102b, 0x50400001, 
+0x27642800, 0x8f820108, 0x10820004, 0x0, 0x8f820104, 0x14820007, 
+0x24050005, 0x8ee201a4, 0x4821, 0x24420001, 0xaee201a4, 0x80028b6, 
+0x8ee201a4, 0xac6a0000, 0xac6b0004, 0x8ee27254, 0xa467000e, 0xac650018, 
+0xac620008, 0x8ee204d4, 0xac62001c, 0x8ee204b8, 0xac620010, 0xaf840100, 
+0x92e204dc, 0x14400036, 0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 
+0x2e22021, 0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 
 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 
 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 
-0x10a20005, 0x0, 0x80027c8, 0x0, 0x14a00005, 0x0, 
+0x10a20005, 0x0, 0x80028a0, 0x0, 0x14a00005, 0x0, 
 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 
-0x50400013, 0xac800000, 0x80027de, 0x0, 0x8ee24e18, 0x24030040, 
+0x50400013, 0xac800000, 0x80028b6, 0x0, 0x8ee24e18, 0x24030040, 
 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 
 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 
-0x24020001, 0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27254, 
-0x3c040001, 0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x800284a, 
-0x34a5f016, 0x8ee37254, 0xa462000c, 0x8ee37254, 0x9582000e, 0xa462000e, 
-0x800284e, 0x24e70004, 0x8f830100, 0x27623000, 0x24640020, 0x82102b, 
-0x50400001, 0x27642800, 0x8f820108, 0x14820007, 0x24050005, 0x8ee201a4, 
-0x4821, 0x24420001, 0xaee201a4, 0x8002842, 0x8ee201a4, 0xac6a0000, 
-0xac6b0004, 0x8ee27254, 0xa467000e, 0xac650018, 0xac620008, 0x8ee204d4, 
-0xac62001c, 0x8ee204b8, 0xac620010, 0xaf840100, 0x92e204dc, 0x14400036, 
-0x24090001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 
+0x24020001, 0xac820004, 0x1520000b, 0x3c050004, 0x3c040001, 0x24844b08, 
+0xafab0010, 0xafa00014, 0x8ee604d4, 0x34a5f017, 0xc002403, 0x30e7ffff, 
+0x80028e1, 0x0, 0x8ee27254, 0x3c050001, 0x30e4ffff, 0x441021, 
+0xaee27254, 0x8ee2724c, 0x8ee37254, 0x34a53800, 0x441021, 0xaee2724c, 
+0x3651021, 0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 
+0xaee27254, 0x8ee304d4, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 
+0xaee304d4, 0x8ee304d4, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 
+0x2403fff7, 0x431024, 0xaf820060, 0x8fbf0020, 0x3e00008, 0x27bd0028, 
+0x27bdffe0, 0xafbf0018, 0x8ee304d8, 0x8ee204d0, 0x10620189, 0x0, 
+0x8ee204d8, 0x8ee304ec, 0x21100, 0x621821, 0x94670008, 0x92e204dd, 
+0x8c680000, 0x8c690004, 0x10400023, 0x946a000a, 0x8ee204b8, 0x34460400, 
+0x31420200, 0x1040001f, 0x0, 0x96e2045a, 0x30420010, 0x1040001b, 
+0x3c028000, 0x3c010001, 0x370821, 0xac2283c8, 0x8ee27254, 0x9464000e, 
+0x3c050001, 0x34a53800, 0x24420004, 0xaee27254, 0x8ee37254, 0x42400, 
+0x3651021, 0x3c010001, 0x370821, 0xac2483cc, 0x62182b, 0x14600005, 
+0x24e70004, 0x8ee27254, 0x3c03ffff, 0x431021, 0xaee27254, 0x8ee27254, 
+0x8002917, 0xaee27248, 0x8ee604b8, 0x8ee2725c, 0x30e4ffff, 0x44102a, 
+0x10400015, 0x0, 0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 
+0x8ee2725c, 0x1c400007, 0x44102a, 0x8ee2725c, 0x3c030001, 0x431021, 
+0xaee2725c, 0x8ee2725c, 0x44102a, 0x10400006, 0x0, 0x8ee201b4, 
+0x24420001, 0xaee201b4, 0x8002a72, 0x8ee201b4, 0x3c020001, 0x571021, 
+0x8c4283c8, 0x54400001, 0x24e7fffc, 0x31420004, 0x104000b9, 0x30e2ffff, 
+0x3c020001, 0x571021, 0x8c4283c8, 0x1040002f, 0x5021, 0x8f840100, 
+0x27623000, 0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 
+0x10a20032, 0x0, 0x8f820104, 0x10a2002f, 0x24020015, 0xac880000, 
+0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 0x8ee204d8, 
+0x3c030001, 0x771821, 0x8c6383cc, 0xac860010, 0x431025, 0xac82001c, 
+0xaf850100, 0x92e204dc, 0x14400066, 0x240a0001, 0x8ee24e18, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 
+0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020015, 0xac620000, 
+0x24020001, 0x80029bf, 0xac620004, 0x8f840100, 0x27623000, 0x24850020, 
+0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a20004, 0x0, 
+0x8f820104, 0x14a20006, 0x24020006, 0x8ee201a4, 0x24420001, 0xaee201a4, 
+0x80029bf, 0x8ee201a4, 0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 
+0xac820018, 0xac830008, 0x8ee204d8, 0xac860010, 0xac82001c, 0xaf850100, 
+0x92e204dc, 0x14400037, 0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 
+0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 
+0x8ee24e1c, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
+0x8ee24e1c, 0x8ee54e18, 0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 
+0x24420001, 0x10a20005, 0x0, 0x80029a9, 0x0, 0x14a00005, 
+0x0, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 
+0x2c420011, 0x50400013, 0xac800000, 0x80029bf, 0x0, 0x8ee24e18, 
+0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 
+0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 
+0xac820000, 0x24020001, 0xac820004, 0x1540000a, 0x24020001, 0xafa90010, 
+0x8ee27254, 0x3c040001, 0x24844af0, 0x3c050004, 0xafa20014, 0x8ee604d4, 
+0x8002a4f, 0x34a5f204, 0xa2e204dd, 0x8ee204d8, 0x8ee304ec, 0x8ee47248, 
+0x3c060001, 0x34c63800, 0x3c010001, 0x370821, 0xac2083c8, 0x3c010001, 
+0x370821, 0xac2083cc, 0x21100, 0x431021, 0xac44000c, 0x8ee27254, 
+0x2405fff8, 0x30e3ffff, 0x431021, 0x24420007, 0x451024, 0x24630007, 
+0xaee27248, 0x8ee2725c, 0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 
+0x3661021, 0x82202b, 0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 
+0xaee27248, 0x8ee27248, 0x8002a64, 0xaee27254, 0x10400073, 0x0, 
+0x8f830100, 0x27623000, 0x24640020, 0x82102b, 0x14400002, 0x5021, 
+0x27642800, 0x8f820108, 0x10820004, 0x0, 0x8f820104, 0x14820006, 
+0x24050005, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x8002a46, 0x8ee201a4, 
+0xac680000, 0xac690004, 0x8ee27254, 0xa467000e, 0xac650018, 0xac620008, 
+0x8ee204d8, 0xac660010, 0xac62001c, 0xaf840100, 0x92e204dc, 0x14400036, 
+0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c820000, 
 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 0x24030040, 
 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 0x24420001, 
 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 0x0, 
-0x800282c, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 
+0x8002a30, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 
 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
-0x8002842, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 
+0x8002a46, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 
 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 
 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 
-0x1520000b, 0x3c050004, 0x3c040001, 0x248448f8, 0xafab0010, 0xafa00014, 
-0x8ee604d4, 0x34a5f017, 0xc0023a7, 0x30e7ffff, 0x800286d, 0x0, 
-0x8ee27254, 0x3c050001, 0x30e4ffff, 0x441021, 0xaee27254, 0x8ee2724c, 
-0x8ee37254, 0x34a53800, 0x441021, 0xaee2724c, 0x3651021, 0x62182b, 
-0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 0xaee27254, 0x8ee304d4, 
-0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d4, 0x8ee304d4, 
-0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 0x2403fff7, 0x431024, 
-0xaf820060, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x27bdffe0, 0xafbf0018, 
-0x8ee304d8, 0x8ee204d0, 0x10620180, 0x0, 0x8ee204d8, 0x8ee304ec, 
-0x21100, 0x621821, 0x94670008, 0x92e204dd, 0x8c680000, 0x8c690004, 
-0x10400023, 0x946a000a, 0x8ee204b8, 0x34460400, 0x31420200, 0x1040001f, 
-0x0, 0x96e2045a, 0x30420010, 0x1040001b, 0x3c028000, 0x3c010001, 
-0x370821, 0xac2283c8, 0x8ee27254, 0x9464000e, 0x3c050001, 0x34a53800, 
-0x24420004, 0xaee27254, 0x8ee37254, 0x42400, 0x3651021, 0x3c010001, 
-0x370821, 0xac2483cc, 0x62182b, 0x14600005, 0x24e70004, 0x8ee27254, 
-0x3c03ffff, 0x431021, 0xaee27254, 0x8ee27254, 0x80028a3, 0xaee27248, 
-0x8ee604b8, 0x8ee2725c, 0x30e4ffff, 0x44102a, 0x10400015, 0x0, 
-0x8f8200d8, 0x8ee37248, 0x431023, 0xaee2725c, 0x8ee2725c, 0x1c400007, 
-0x44102a, 0x8ee2725c, 0x3c030001, 0x431021, 0xaee2725c, 0x8ee2725c, 
-0x44102a, 0x10400006, 0x0, 0x8ee201b4, 0x24420001, 0xaee201b4, 
-0x80029f5, 0x8ee201b4, 0x3c020001, 0x571021, 0x8c4283c8, 0x54400001, 
-0x24e7fffc, 0x31420004, 0x104000b3, 0x30e2ffff, 0x3c020001, 0x571021, 
-0x8c4283c8, 0x1040002c, 0x5021, 0x8f840100, 0x27623000, 0x24850020, 
-0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x10a2002c, 0x24020015, 
-0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 
-0x8ee204d8, 0x3c030001, 0x771821, 0x8c6383cc, 0xac860010, 0x431025, 
-0xac82001c, 0xaf850100, 0x92e204dc, 0x14400063, 0x240a0001, 0x8ee24e18, 
-0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 
-0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020015, 
-0xac620000, 0x24020001, 0x8002945, 0xac620004, 0x8f840100, 0x27623000, 
-0x24850020, 0xa2102b, 0x50400001, 0x27652800, 0x8f820108, 0x14a20006, 
-0x24020006, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x8002945, 0x8ee201a4, 
-0xac880000, 0xac890004, 0x8ee37254, 0xa487000e, 0xac820018, 0xac830008, 
-0x8ee204d8, 0xac860010, 0xac82001c, 0xaf850100, 0x92e204dc, 0x14400037, 
-0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 0x8c830000, 
-0x24020005, 0x1462001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 
-0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 
-0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 
-0x0, 0x800292f, 0x0, 0x14a00005, 0x0, 0x8f820108, 
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x8002945, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 
-0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 
-0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 
-0xac820004, 0x1540000a, 0x24020001, 0xafa90010, 0x8ee27254, 0x3c040001, 
-0x248448e0, 0x3c050004, 0xafa20014, 0x8ee604d4, 0x80029d2, 0x34a5f204, 
-0xa2e204dd, 0x8ee204d8, 0x8ee304ec, 0x8ee47248, 0x3c060001, 0x34c63800, 
-0x3c010001, 0x370821, 0xac2083c8, 0x3c010001, 0x370821, 0xac2083cc, 
-0x21100, 0x431021, 0xac44000c, 0x8ee27254, 0x2405fff8, 0x30e3ffff, 
-0x431021, 0x24420007, 0x451024, 0x24630007, 0xaee27248, 0x8ee2725c, 
-0x8ee47248, 0x651824, 0x431023, 0xaee2725c, 0x3661021, 0x82202b, 
-0x14800004, 0x3c03ffff, 0x8ee27248, 0x431021, 0xaee27248, 0x8ee27248, 
-0x80029e7, 0xaee27254, 0x10400070, 0x0, 0x8f830100, 0x27623000, 
-0x24640020, 0x82102b, 0x14400002, 0x5021, 0x27642800, 0x8f820108, 
-0x14820006, 0x24050005, 0x8ee201a4, 0x24420001, 0xaee201a4, 0x80029c9, 
-0x8ee201a4, 0xac680000, 0xac690004, 0x8ee27254, 0xa467000e, 0xac650018, 
-0xac620008, 0x8ee204d8, 0xac660010, 0xac62001c, 0xaf840100, 0x92e204dc, 
-0x14400036, 0x240a0001, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e22021, 
-0x8c820000, 0x1445001f, 0x0, 0x8ee34e18, 0x8ee24e1c, 0x1062001b, 
-0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e1c, 0x8ee54e18, 
-0x24420001, 0x10430007, 0x0, 0x8ee24e1c, 0x24420001, 0x10a20005, 
-0x0, 0x80029b3, 0x0, 0x14a00005, 0x0, 0x8f820108, 
-0x24420020, 0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x80029c9, 0x0, 0x8ee24e18, 0x24030040, 0x24420001, 
-0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 
-0x210c0, 0x24424e28, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 
-0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001, 0x248448f8, 0x3c050004, 
-0xafa90010, 0xafa00014, 0x8ee604d4, 0x34a5f237, 0xc0023a7, 0x30e7ffff, 
-0x80029f5, 0x0, 0x8ee27254, 0x451021, 0xaee27254, 0x8ee2725c, 
-0x8ee37254, 0x3c040001, 0x34843800, 0xa2e004dd, 0x451023, 0xaee2725c, 
-0x3641021, 0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 
-0xaee27254, 0x8ee304d8, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 
-0xaee304d8, 0x8ee304d8, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 
-0x2403fff7, 0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
-0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820100, 0x8ee34e1c, 0x8f820104, 
-0x8f850108, 0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ee24e1c, 
-0x24420001, 0xaee24e1c, 0x8ee24e1c, 0x8ee34e1c, 0x210c0, 0x24424e28, 
-0x2e22021, 0x8ee24e18, 0x8c870004, 0x14620007, 0xa03021, 0x8f820108, 
-0x24420020, 0xaf820108, 0x8f820108, 0x8002a25, 0xac800000, 0x8ee24e1c, 
-0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e1c, 0x24420001, 
-0x210c0, 0x24424e28, 0x2e22021, 0x8c820004, 0x8f830108, 0x21140, 
-0x621821, 0xaf830108, 0xac800000, 0x8cc30018, 0x2c620002, 0x144000b7, 
-0x2c620004, 0x5440008a, 0x24030040, 0x2c620007, 0x104000b2, 0x2c620005, 
-0x144000b0, 0x0, 0x8ee204e0, 0x471021, 0xaee204e0, 0x8ee204e0, 
-0x8f43023c, 0x43102b, 0x144000b2, 0x0, 0x8ee304d4, 0x8ee204e8, 
-0x506200ae, 0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
-0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 0x8ee201a0, 
-0x8021, 0x24420001, 0xaee201a0, 0x8002a93, 0x8ee201a0, 0x8ee204d4, 
-0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, 
-0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 
-0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 0x24420001, 0x10430007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 0x0, 0x8002a7d, 
-0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 0x8002a93, 
-0x0, 0x8ee24e20, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 
-0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, 0xafa00014, 0xafa20010, 
-0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f006, 0x16000003, 
-0x24020001, 0x8002ae9, 0xa2e204e4, 0x8ee2016c, 0x24420001, 0xaee2016c, 
-0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee204e8, 0x8f42023c, 
-0x5040003c, 0xaee07264, 0x8ee20180, 0x24420001, 0xaee20180, 0x8ee20180, 
-0x8002ae9, 0xaee07264, 0x8ee204f4, 0x24420001, 0x50430003, 0x1021, 
-0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 0x8cc30018, 0x21080, 
-0x571021, 0x8c4404f8, 0x24020003, 0x1462000f, 0x0, 0x3c020001, 
-0x571021, 0x904283a1, 0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, 
-0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 0x306300ff, 0x8002ad9, 
-0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, 
-0x641821, 0x306301ff, 0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, 
-0x34420040, 0x8002ae9, 0xaee20000, 0x94c7000e, 0x8cc2001c, 0x3c040001, 
-0x24844910, 0xafa60014, 0xafa20010, 0x8cc60018, 0x3c050008, 0xc0023a7, 
-0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x27bdff98, 
-0xafbf0060, 0xafbe005c, 0xafb60058, 0xafb50054, 0xafb40050, 0xafb3004c, 
-0xafb20048, 0xafb10044, 0xafb00040, 0x8f830108, 0x8f820104, 0xafa00024, 
-0x106203d9, 0xafa0002c, 0x3c1e0001, 0x37de3800, 0x3c0bffff, 0x8f930108, 
-0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, 0x104003c1, 0x31080, 
-0x3c010001, 0x220821, 0x8c224920, 0x400008, 0x0, 0x9663000e, 
-0x8ee2724c, 0x8ee404e0, 0x431021, 0xaee2724c, 0x8e63001c, 0x96e20458, 
-0x24840001, 0xaee404e0, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d4, 
-0x8f42023c, 0x82202b, 0x148003ab, 0x0, 0x8f830120, 0x27623800, 
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002b73, 
+0x1540000c, 0x30e5ffff, 0x3c040001, 0x24844b08, 0x3c050004, 0xafa90010, 
+0xafa00014, 0x8ee604d4, 0x34a5f237, 0xc002403, 0x30e7ffff, 0x8002a72, 
+0x0, 0x8ee27254, 0x451021, 0xaee27254, 0x8ee2725c, 0x8ee37254, 
+0x3c040001, 0x34843800, 0xa2e004dd, 0x451023, 0xaee2725c, 0x3641021, 
+0x62182b, 0x14600004, 0x3c03ffff, 0x8ee27254, 0x431021, 0xaee27254, 
+0x8ee304d8, 0x96e20458, 0x24630001, 0x2442ffff, 0x621824, 0xaee304d8, 
+0x8ee304d8, 0x8ee204d0, 0x14620005, 0x0, 0x8f820060, 0x2403fff7, 
+0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 
+0xafbf001c, 0xafb00018, 0x8f820100, 0x8ee34e1c, 0x8f820104, 0x8f850108, 
+0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ee24e1c, 0x24420001, 
+0xaee24e1c, 0x8ee24e1c, 0x8ee34e1c, 0x210c0, 0x24424e28, 0x2e22021, 
+0x8ee24e18, 0x8c870004, 0x14620007, 0xa03021, 0x8f820108, 0x24420020, 
+0xaf820108, 0x8f820108, 0x8002aa2, 0xac800000, 0x8ee24e1c, 0x24030040, 
+0x24420001, 0x50430003, 0x1021, 0x8ee24e1c, 0x24420001, 0x210c0, 
+0x24424e28, 0x2e22021, 0x8c820004, 0x8f830108, 0x21140, 0x621821, 
+0xaf830108, 0xac800000, 0x8cc30018, 0x2c620002, 0x144000ba, 0x2c620004, 
+0x5440008d, 0x24030040, 0x2c620007, 0x104000b5, 0x2c620005, 0x144000b3, 
+0x0, 0x8ee204e0, 0x471021, 0xaee204e0, 0x8ee204e0, 0x8f43023c, 
+0x43102b, 0x144000b5, 0x0, 0x8ee304d4, 0x8ee204e8, 0x506200b1, 
+0xa2e004e4, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 
+0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 
+0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002b13, 
 0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 
 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 
 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 
 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8002b5d, 0x0, 0x14600005, 0x0, 0x8f820128, 
+0x24030040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee54e20, 
+0x24420001, 0x10430007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 
+0x0, 0x8002afd, 0x0, 0x14a00005, 0x0, 0x8f820128, 
 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x8002b73, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, 
-0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 
-0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, 
-0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, 
-0xc0023a7, 0xafab0038, 0x8fab0038, 0x12000307, 0x240c0001, 0x8002e8b, 
-0x0, 0x966c001c, 0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024, 
-0xae62001c, 0x8e75001c, 0x8ee204ec, 0x8ee404ec, 0x151900, 0x621021, 
-0x8c52000c, 0x92e27b88, 0x641821, 0x9476000a, 0x14400003, 0x32c20002, 
-0xaef27b94, 0xaef57b8c, 0x1040004b, 0x8021, 0x96e2045a, 0x30420002, 
-0x10400047, 0x0, 0x8e63001c, 0x8ee204ec, 0x32100, 0x821021, 
-0x8c42000c, 0x37e1821, 0x24420022, 0x43102b, 0x1440000a, 0x24050014, 
-0x8ee204ec, 0x821021, 0x8c44000c, 0xafab0038, 0xc002edf, 0x2484000e, 
-0x8fab0038, 0x8002bc7, 0x3050ffff, 0x8ee204ec, 0x821021, 0x8c42000c, 
-0x9450000e, 0x94430010, 0x94440012, 0x94450014, 0x2038021, 0x2048021, 
-0x2058021, 0x94430016, 0x94440018, 0x9445001a, 0x2038021, 0x2048021, 
-0x2058021, 0x9443001c, 0x9444001e, 0x94420020, 0x2038021, 0x2048021, 
-0x2028021, 0x101c02, 0x3202ffff, 0x628021, 0x8e63001c, 0x8ee204ec, 
-0x102402, 0x32900, 0xa21021, 0x8c43000c, 0x3202ffff, 0x828021, 
-0x37e1021, 0x24630018, 0x62182b, 0x14600009, 0x0, 0x8ee204ec, 
-0xa21021, 0x8c43000c, 0x101027, 0x3c01ffff, 0x230821, 0x8002be4, 
-0xa4220018, 0x8ee204ec, 0xa21021, 0x8c43000c, 0x101027, 0xa4620018, 
-0x96e2045a, 0x8821, 0x30420008, 0x14400063, 0xa021, 0x8e63001c, 
-0x8ee204ec, 0x33100, 0xc21021, 0x8c42000c, 0x37e1821, 0x24420022, 
-0x43102b, 0x14400035, 0x0, 0x8ee204ec, 0xc21021, 0x8c42000c, 
-0x24470010, 0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x8ee204ec, 
-0x94f10000, 0xc21021, 0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b, 
-0x14400002, 0x2634ffec, 0xeb3821, 0x8ee204ec, 0x90e30001, 0xc21021, 
-0x8c42000c, 0x2447001a, 0x37e1021, 0xe2102b, 0x14400002, 0x2838821, 
+0xac800000, 0x8002b13, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 
+0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 
+0xac820004, 0x5600000b, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844b14, 
+0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc002403, 
+0x34a5f006, 0x16000003, 0x24020001, 0x8002b69, 0xa2e204e4, 0x8ee2016c, 
+0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 
+0xaee204e8, 0x8f42023c, 0x5040003c, 0xaee07264, 0x8ee20180, 0x24420001, 
+0xaee20180, 0x8ee20180, 0x8002b69, 0xaee07264, 0x8ee204f4, 0x24420001, 
+0x50430003, 0x1021, 0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 
+0x8cc30018, 0x21080, 0x571021, 0x8c4404f8, 0x24020003, 0x1462000f, 
+0x0, 0x3c020001, 0x571021, 0x904283a1, 0x10400014, 0x0, 
+0x8ee201c8, 0x8ee35230, 0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 
+0x306300ff, 0x8002b59, 0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 
+0xaee201c4, 0x8ee201cc, 0x641821, 0x306301ff, 0xaee30e00, 0x441021, 
+0xaee201cc, 0x8ee20000, 0x34420040, 0x8002b69, 0xaee20000, 0x94c7000e, 
+0x8cc2001c, 0x3c040001, 0x24844b20, 0xafa60014, 0xafa20010, 0x8cc60018, 
+0x3c050008, 0xc002403, 0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, 
+0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058, 0xafb50054, 
+0xafb40050, 0xafb3004c, 0xafb20048, 0xafb10044, 0xafb00040, 0x8f830108, 
+0x8f820104, 0xafa00024, 0x106203df, 0xafa0002c, 0x3c1e0001, 0x37de3800, 
+0x3c0bffff, 0x8f930108, 0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, 
+0x104003c7, 0x31080, 0x3c010001, 0x220821, 0x8c224b30, 0x400008, 
+0x0, 0x9663000e, 0x8ee2724c, 0x8ee404e0, 0x431021, 0xaee2724c, 
+0x8e63001c, 0x96e20458, 0x24840001, 0xaee404e0, 0x24630001, 0x2442ffff, 
+0x621824, 0xaee304d4, 0x8f42023c, 0x82202b, 0x148003b1, 0x0, 
+0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 
+0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 0x0, 
+0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002bf6, 0x8ee201a0, 
+0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 0xac620008, 
+0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 
+0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 0x24100001, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 
+0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x240c0040, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
+0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
+0x8002be0, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
+0x8002bf6, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, 0x504c0003, 
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004, 
+0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844b14, 0xafa00014, 
+0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403, 
+0xafab0038, 0x8fab0038, 0x1200030a, 0x240c0001, 0x8002f11, 0x0, 
+0x966c001c, 0xafac002c, 0x9662001e, 0x3c0c8000, 0xafac0024, 0xae62001c, 
+0x8e75001c, 0x8ee204ec, 0x8ee404ec, 0x151900, 0x621021, 0x8c52000c, 
+0x92e27b88, 0x641821, 0x9476000a, 0x14400003, 0x32c20002, 0xaef27b94, 
+0xaef57b8c, 0x1040004b, 0x8021, 0x96e2045a, 0x30420002, 0x10400047, 
+0x0, 0x8e63001c, 0x8ee204ec, 0x32100, 0x821021, 0x8c42000c, 
+0x37e1821, 0x24420022, 0x43102b, 0x1440000a, 0x24050014, 0x8ee204ec, 
+0x821021, 0x8c44000c, 0xafab0038, 0xc002f65, 0x2484000e, 0x8fab0038, 
+0x8002c4a, 0x3050ffff, 0x8ee204ec, 0x821021, 0x8c42000c, 0x9450000e, 
+0x94430010, 0x94440012, 0x94450014, 0x2038021, 0x2048021, 0x2058021, 
+0x94430016, 0x94440018, 0x9445001a, 0x2038021, 0x2048021, 0x2058021, 
+0x9443001c, 0x9444001e, 0x94420020, 0x2038021, 0x2048021, 0x2028021, 
+0x101c02, 0x3202ffff, 0x628021, 0x8e63001c, 0x8ee204ec, 0x102402, 
+0x32900, 0xa21021, 0x8c43000c, 0x3202ffff, 0x828021, 0x37e1021, 
+0x24630018, 0x62182b, 0x14600009, 0x0, 0x8ee204ec, 0xa21021, 
+0x8c43000c, 0x101027, 0x3c01ffff, 0x230821, 0x8002c67, 0xa4220018, 
+0x8ee204ec, 0xa21021, 0x8c43000c, 0x101027, 0xa4620018, 0x96e2045a, 
+0x8821, 0x30420008, 0x14400063, 0xa021, 0x8e63001c, 0x8ee204ec, 
+0x33100, 0xc21021, 0x8c42000c, 0x37e1821, 0x24420022, 0x43102b, 
+0x14400035, 0x0, 0x8ee204ec, 0xc21021, 0x8c42000c, 0x24470010, 
+0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x8ee204ec, 0x94f10000, 
+0xc21021, 0x8c42000c, 0x24470016, 0x37e1021, 0xe2102b, 0x14400002, 
+0x2634ffec, 0xeb3821, 0x8ee204ec, 0x90e30001, 0xc21021, 0x8c42000c, 
+0x2447001a, 0x37e1021, 0xe2102b, 0x14400002, 0x2838821, 0xeb3821, 
+0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 0xe2102b, 0x50400001, 
 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 0xe2102b, 
 0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 0x37e1021, 
-0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x24e70002, 0x2228821, 
-0x37e1021, 0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x8002c45, 
-0x2228821, 0x8ee204ec, 0xc21021, 0x8c43000c, 0x8ee204ec, 0x94710010, 
-0x8ee304ec, 0xc21021, 0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec, 
-0x90840017, 0x8ee304ec, 0x9442001a, 0x2848821, 0xc31821, 0x8c65000c, 
-0x8ee304ec, 0x2228821, 0x8ee204ec, 0xc31821, 0xc21021, 0x8c44000c, 
-0x8c62000c, 0x94a3001c, 0x9484001e, 0x94420020, 0x2238821, 0x2248821, 
-0x2228821, 0x111c02, 0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, 
-0x628821, 0x32c20001, 0x104000b2, 0x0, 0x96e2045a, 0x30420001, 
-0x104000ae, 0x32c20080, 0x10400008, 0x0, 0x92e27b88, 0x14400005, 
-0x0, 0x240c0001, 0xa2ec7b88, 0xaef57b8c, 0xaef27b94, 0x8ee304ec, 
-0x151100, 0x431021, 0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b, 
-0x14400008, 0xe02021, 0x2405000e, 0xc002edf, 0xafab0038, 0x3042ffff, 
-0x8fab0038, 0x8002c7e, 0x2028021, 0x94e60000, 0x24e70002, 0x94e50000, 
-0x24e70002, 0x94e30000, 0x24e70002, 0x94e20000, 0x24e70002, 0x94e40000, 
-0x24e70002, 0x2068021, 0x2058021, 0x2038021, 0x2028021, 0x94e20000, 
-0x94e30002, 0x2048021, 0x2028021, 0x2038021, 0x101c02, 0x3202ffff, 
-0x628021, 0x101c02, 0x3202ffff, 0x8ee47b8c, 0x628021, 0x14950004, 
-0x3205ffff, 0x96620016, 0x8002c8c, 0x512021, 0x96620016, 0x542021, 
-0x41402, 0x3083ffff, 0x432021, 0x852023, 0x41402, 0x822021, 
-0x3084ffff, 0x50800001, 0x3404ffff, 0x8ee27b94, 0x24430017, 0x37e1021, 
-0x62102b, 0x50400001, 0x6b1821, 0x90630000, 0x24020011, 0x14620031, 
-0x24020006, 0x8ee27b94, 0x37e1821, 0x24420028, 0x43102b, 0x14400018, 
+0xe2102b, 0x50400001, 0xeb3821, 0x94e20000, 0x8002cc8, 0x2228821, 
+0x8ee204ec, 0xc21021, 0x8c43000c, 0x8ee204ec, 0x94710010, 0x8ee304ec, 
+0xc21021, 0x8c44000c, 0xc31821, 0x8c62000c, 0x2634ffec, 0x90840017, 
+0x8ee304ec, 0x9442001a, 0x2848821, 0xc31821, 0x8c65000c, 0x8ee304ec, 
+0x2228821, 0x8ee204ec, 0xc31821, 0xc21021, 0x8c44000c, 0x8c62000c, 
+0x94a3001c, 0x9484001e, 0x94420020, 0x2238821, 0x2248821, 0x2228821, 
+0x111c02, 0x3222ffff, 0x628821, 0x111c02, 0x3222ffff, 0x628821, 
+0x32c20001, 0x104000b2, 0x0, 0x96e2045a, 0x30420001, 0x104000ae, 
+0x32c20080, 0x10400008, 0x0, 0x92e27b88, 0x14400005, 0x0, 
+0x240c0001, 0xa2ec7b88, 0xaef57b8c, 0xaef27b94, 0x8ee304ec, 0x151100, 
+0x431021, 0x8c47000c, 0x37e1821, 0x24e2000e, 0x43102b, 0x14400008, 
+0xe02021, 0x2405000e, 0xc002f65, 0xafab0038, 0x3042ffff, 0x8fab0038, 
+0x8002d01, 0x2028021, 0x94e60000, 0x24e70002, 0x94e50000, 0x24e70002, 
+0x94e30000, 0x24e70002, 0x94e20000, 0x24e70002, 0x94e40000, 0x24e70002, 
+0x2068021, 0x2058021, 0x2038021, 0x2028021, 0x94e20000, 0x94e30002, 
+0x2048021, 0x2028021, 0x2038021, 0x101c02, 0x3202ffff, 0x628021, 
+0x101c02, 0x3202ffff, 0x8ee47b8c, 0x628021, 0x14950004, 0x3205ffff, 
+0x96620016, 0x8002d0f, 0x512021, 0x96620016, 0x542021, 0x41402, 
+0x3083ffff, 0x432021, 0x852023, 0x41402, 0x822021, 0x3084ffff, 
+0x50800001, 0x3404ffff, 0x8ee27b94, 0x24430017, 0x37e1021, 0x62102b, 
+0x50400001, 0x6b1821, 0x90630000, 0x24020011, 0x14620031, 0x24020006, 
+0x8ee27b94, 0x37e1821, 0x24420028, 0x43102b, 0x14400018, 0x0, 
+0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 0x3c01ffff, 0x220821, 
+0x94220028, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 
+0x14400004, 0x41027, 0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 
+0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002d82, 0xa4240028, 0x8ee27b8c, 
+0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420028, 0x822021, 0x41c02, 
+0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 
+0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0x8002d82, 0xa4440028, 
+0x1462002f, 0x37e1821, 0x8ee27b94, 0x24420032, 0x43102b, 0x14400018, 
 0x0, 0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 0x3c01ffff, 
-0x220821, 0x94220028, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 
+0x220821, 0x94220032, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 
 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 0x14400002, 0x41027, 
-0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002cff, 0xa4240028, 
-0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420028, 0x822021, 
+0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002d82, 0xa4240032, 
+0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420032, 0x822021, 
 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 0x41027, 
-0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0x8002cff, 
-0xa4440028, 0x1462002f, 0x37e1821, 0x8ee27b94, 0x24420032, 0x43102b, 
-0x14400018, 0x0, 0x8ee27b8c, 0x12a2000a, 0x32c20100, 0x8ee27b94, 
-0x3c01ffff, 0x220821, 0x94220032, 0x822021, 0x41c02, 0x3082ffff, 
-0x622021, 0x32c20100, 0x14400004, 0x41027, 0x92e27b88, 0x14400002, 
-0x41027, 0x3044ffff, 0x8ee27b94, 0x3c01ffff, 0x220821, 0x8002cff, 
-0xa4240032, 0x8ee27b8c, 0x12a20008, 0x32c20100, 0x8ee27b94, 0x94420032, 
-0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x32c20100, 0x14400004, 
-0x41027, 0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 
-0xa4440032, 0x8fac0024, 0x1180002c, 0x37e1821, 0x8e420000, 0xae42fffc, 
-0x2642000a, 0x43102b, 0x1440001b, 0x34038100, 0x26430004, 0x37e1021, 
-0x62102b, 0x14400003, 0x602021, 0x6b1821, 0x602021, 0x8c620000, 
-0x24630004, 0xae420000, 0x37e1021, 0x62102b, 0x50400001, 0x6b1821, 
-0x8c620000, 0xac820000, 0x34028100, 0xa4620000, 0x24630002, 0x37e1021, 
-0x62102b, 0x50400001, 0x6b1821, 0x97ac002e, 0x8002d29, 0xa46c0000, 
-0x8e420004, 0x8e440008, 0xa6430008, 0x97ac002e, 0xa64c000a, 0xae420000, 
-0xae440004, 0x9662000e, 0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e, 
-0x8ee3724c, 0x621821, 0xaee3724c, 0xafb20018, 0x8ee3724c, 0xafa3001c, 
-0x8ee2724c, 0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 0x431024, 
-0xafa2001c, 0x32c20080, 0x1040000c, 0x32c20100, 0x8ee27b98, 0x24430001, 
+0x92e27b88, 0x14400002, 0x41027, 0x3044ffff, 0x8ee27b94, 0xa4440032, 
+0x8fac0024, 0x1180002c, 0x37e1821, 0x8e420000, 0xae42fffc, 0x2642000a, 
+0x43102b, 0x1440001b, 0x34038100, 0x26430004, 0x37e1021, 0x62102b, 
+0x14400003, 0x602021, 0x6b1821, 0x602021, 0x8c620000, 0x24630004, 
+0xae420000, 0x37e1021, 0x62102b, 0x50400001, 0x6b1821, 0x8c620000, 
+0xac820000, 0x34028100, 0xa4620000, 0x24630002, 0x37e1021, 0x62102b, 
+0x50400001, 0x6b1821, 0x97ac002e, 0x8002dac, 0xa46c0000, 0x8e420004, 
+0x8e440008, 0xa6430008, 0x97ac002e, 0xa64c000a, 0xae420000, 0xae440004, 
+0x9662000e, 0x2652fffc, 0x24420004, 0xa662000e, 0x9662000e, 0x8ee3724c, 
+0x621821, 0xaee3724c, 0xafb20018, 0x8ee3724c, 0xafa3001c, 0x8ee2724c, 
+0x2c42003c, 0x10400004, 0x24620001, 0x2403fffe, 0x431024, 0xafa2001c, 
+0x32c20080, 0x1040000c, 0x32c20100, 0x8ee27b98, 0x24430001, 0x210c0, 
+0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 0xac437b9c, 0xac447ba0, 
+0x8002e98, 0xaee0724c, 0x10400072, 0x0, 0x8ee27b98, 0x24430001, 
 0x210c0, 0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 0xac437b9c, 
-0xac447ba0, 0x8002e15, 0xaee0724c, 0x10400072, 0x0, 0x8ee27b98, 
-0x24430001, 0x210c0, 0x571021, 0xaee37b98, 0x8fa30018, 0x8fa4001c, 
-0xac437b9c, 0xac447ba0, 0x8ee27b98, 0x10400063, 0x4821, 0x5021, 
-0x8f8200f0, 0x24480008, 0x27621800, 0x102102b, 0x50400001, 0x27681000, 
-0x8f8200f4, 0x15020007, 0x0, 0x8ee201b0, 0x8021, 0x24420001, 
-0xaee201b0, 0x8002d6f, 0x8ee201b0, 0x8f8300f0, 0x24100001, 0x1571021, 
-0x8c447b9c, 0x8c457ba0, 0xac640000, 0xac650004, 0xaf8800f0, 0x16000006, 
-0x2ea1021, 0x8ee20088, 0x24420001, 0xaee20088, 0x8002db4, 0x8ee20088, 
-0x8c427ba0, 0x8ee400e0, 0x8ee500e4, 0x8ee67b8c, 0x401821, 0x1021, 
-0xa32821, 0xa3382b, 0x822021, 0x872021, 0x8ee204ec, 0xc93021, 
-0x63100, 0xaee400e0, 0xaee500e4, 0xc23021, 0x94c2000a, 0x240c0002, 
-0x21142, 0x30430003, 0x106c0016, 0x28620003, 0x10400005, 0x240c0001, 
-0x106c0008, 0x0, 0x8002db4, 0x0, 0x240c0003, 0x106c0017, 
-0x0, 0x8002db4, 0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001, 
-0x2c640001, 0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8002db4, 
-0x8ee300ec, 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 
-0xaee200f0, 0xaee300f4, 0x8ee200f0, 0x8002db4, 0x8ee300f4, 0x8ee200f8, 
-0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 
-0x8ee200f8, 0x8ee300fc, 0x8ee27b98, 0x25290001, 0x122102b, 0x1440ffa0, 
-0x254a0008, 0xa2e07b88, 0x8002e14, 0xaee07b98, 0x8f8200f0, 0x24470008, 
-0x27621800, 0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 
-0x0, 0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 0x8002dd2, 
-0x8ee201b0, 0x8f8200f0, 0x24100001, 0x8fa30018, 0x8fa4001c, 0xac430000, 
-0xac440004, 0xaf8700f0, 0x16000007, 0x0, 0x8ee20088, 0x24420001, 
-0xaee20088, 0x8ee20088, 0x8002e15, 0xaee0724c, 0x8ee2724c, 0x8ee400e0, 
-0x8ee500e4, 0x240c0002, 0x401821, 0x1021, 0xa32821, 0xa3302b, 
-0x822021, 0x862021, 0x161142, 0x30430003, 0xaee400e0, 0xaee500e4, 
-0x106c0017, 0x2c620003, 0x10400005, 0x240c0001, 0x106c0008, 0x0, 
-0x8002e15, 0xaee0724c, 0x240c0003, 0x106c0019, 0x0, 0x8002e15, 
-0xaee0724c, 0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 
-0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8ee300ec, 0x8002e15, 0xaee0724c, 
+0xac447ba0, 0x8ee27b98, 0x10400063, 0x4821, 0x5021, 0x8f8200f0, 
+0x24480008, 0x27621800, 0x102102b, 0x50400001, 0x27681000, 0x8f8200f4, 
+0x15020007, 0x0, 0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 
+0x8002df2, 0x8ee201b0, 0x8f8300f0, 0x24100001, 0x1571021, 0x8c447b9c, 
+0x8c457ba0, 0xac640000, 0xac650004, 0xaf8800f0, 0x16000006, 0x2ea1021, 
+0x8ee20088, 0x24420001, 0xaee20088, 0x8002e37, 0x8ee20088, 0x8c427ba0, 
+0x8ee400e0, 0x8ee500e4, 0x8ee67b8c, 0x401821, 0x1021, 0xa32821, 
+0xa3382b, 0x822021, 0x872021, 0x8ee204ec, 0xc93021, 0x63100, 
+0xaee400e0, 0xaee500e4, 0xc23021, 0x94c2000a, 0x240c0002, 0x21142, 
+0x30430003, 0x106c0016, 0x28620003, 0x10400005, 0x240c0001, 0x106c0008, 
+0x0, 0x8002e37, 0x0, 0x240c0003, 0x106c0017, 0x0, 
+0x8002e37, 0x0, 0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 
+0x441021, 0xaee200e8, 0xaee300ec, 0x8ee200e8, 0x8002e37, 0x8ee300ec, 
 0x8ee200f0, 0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 
-0xaee300f4, 0x8ee200f0, 0x8ee300f4, 0x8002e15, 0xaee0724c, 0x8ee200f8, 
-0x8ee300fc, 0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 
-0x8ee200f8, 0x8ee300fc, 0xaee0724c, 0x8e62001c, 0x96e30458, 0x8ee404e0, 
-0x24420001, 0x2463ffff, 0x431024, 0x24840001, 0xaee204d4, 0xaee404e0, 
-0x8f42023c, 0x82202b, 0x148000a5, 0x0, 0x8f830120, 0x27623800, 
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8002e79, 
-0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 0x8ee504a4, 0x2462001c, 
-0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 
-0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400037, 
-0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
-0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8002e63, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x8002e79, 0x0, 0x8ee24e20, 0x240c0040, 0x24420001, 
-0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 
-0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 0x3c040001, 0x24844904, 
-0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 0x3c050009, 0x34a5f006, 
-0xc0023a7, 0xafab0038, 0x8fab0038, 0x16000003, 0x240c0001, 0x8002ec6, 
-0xa2ec04e4, 0x8ee2016c, 0x24420001, 0xaee2016c, 0x8ee2016c, 0x8ee204d4, 
-0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, 0x8f42023c, 0x10400030, 
-0x0, 0x8ee20180, 0x24420001, 0xaee20180, 0x8002ec6, 0x8ee20180, 
-0x8ee204f4, 0x240c0040, 0x24420001, 0x504c0003, 0x1021, 0x8ee204f4, 
-0x24420001, 0xaee204f4, 0x8ee204f4, 0x8e630018, 0x240c0003, 0x21080, 
-0x571021, 0x146c000f, 0x8c4404f8, 0x3c020001, 0x571021, 0x904283a1, 
-0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, 0x441021, 0xaee201c8, 
-0x8ee201cc, 0x641821, 0x306300ff, 0x8002ec1, 0xaee35230, 0x8ee201c4, 
-0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, 0x641821, 0x306301ff, 
-0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, 0x34420040, 0xaee20000, 
-0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 0x8f820108, 0x27633000, 
-0x43102b, 0x14400002, 0x27622800, 0xaf820108, 0x8f830108, 0x8f820104, 
-0x1462fc2c, 0x0, 0x8fbf0060, 0x8fbe005c, 0x8fb60058, 0x8fb50054, 
-0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, 0x3e00008, 
-0x27bd0068, 0x52843, 0x10a0000d, 0x3021, 0x3c030001, 0x34633800, 
-0x3c07ffff, 0x3631021, 0x82102b, 0x50400001, 0x872021, 0x94820000, 
-0x24840002, 0x24a5ffff, 0x14a0fff8, 0xc23021, 0x61c02, 0x30c2ffff, 
-0x623021, 0x61c02, 0x30c2ffff, 0x623021, 0x3e00008, 0x30c2ffff, 
-0x0, 0x0, 0x27bdff88, 0x240f0001, 0xafbf0070, 0xafbe006c, 
+0xaee300f4, 0x8ee200f0, 0x8002e37, 0x8ee300f4, 0x8ee200f8, 0x8ee300fc, 
+0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, 
+0x8ee300fc, 0x8ee27b98, 0x25290001, 0x122102b, 0x1440ffa0, 0x254a0008, 
+0xa2e07b88, 0x8002e97, 0xaee07b98, 0x8f8200f0, 0x24470008, 0x27621800, 
+0xe2102b, 0x50400001, 0x27671000, 0x8f8200f4, 0x14e20007, 0x0, 
+0x8ee201b0, 0x8021, 0x24420001, 0xaee201b0, 0x8002e55, 0x8ee201b0, 
+0x8f8200f0, 0x24100001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, 
+0xaf8700f0, 0x16000007, 0x0, 0x8ee20088, 0x24420001, 0xaee20088, 
+0x8ee20088, 0x8002e98, 0xaee0724c, 0x8ee2724c, 0x8ee400e0, 0x8ee500e4, 
+0x240c0002, 0x401821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 
+0x862021, 0x161142, 0x30430003, 0xaee400e0, 0xaee500e4, 0x106c0017, 
+0x2c620003, 0x10400005, 0x240c0001, 0x106c0008, 0x0, 0x8002e98, 
+0xaee0724c, 0x240c0003, 0x106c0019, 0x0, 0x8002e98, 0xaee0724c, 
+0x8ee200e8, 0x8ee300ec, 0x24630001, 0x2c640001, 0x441021, 0xaee200e8, 
+0xaee300ec, 0x8ee200e8, 0x8ee300ec, 0x8002e98, 0xaee0724c, 0x8ee200f0, 
+0x8ee300f4, 0x24630001, 0x2c640001, 0x441021, 0xaee200f0, 0xaee300f4, 
+0x8ee200f0, 0x8ee300f4, 0x8002e98, 0xaee0724c, 0x8ee200f8, 0x8ee300fc, 
+0x24630001, 0x2c640001, 0x441021, 0xaee200f8, 0xaee300fc, 0x8ee200f8, 
+0x8ee300fc, 0xaee0724c, 0x8e62001c, 0x96e30458, 0x8ee404e0, 0x24420001, 
+0x2463ffff, 0x431024, 0x24840001, 0xaee204d4, 0xaee404e0, 0x8f42023c, 
+0x82202b, 0x148000a8, 0x0, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 
+0xaee201a0, 0x8002eff, 0x8ee201a0, 0x8ee204d4, 0xac62001c, 0x8ee404a0, 
+0x8ee504a4, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
+0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
+0x92e24e10, 0x14400037, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0x8c830000, 0x24020012, 0x1462001f, 0x0, 0x8ee34e20, 
+0x8ee24e24, 0x1062001b, 0x240c0040, 0x8c820004, 0x24420001, 0xac820004, 
+0x8ee24e24, 0x8ee34e20, 0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 
+0x24420001, 0x10620005, 0x0, 0x8002ee9, 0x0, 0x14600005, 
+0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
+0x2c420011, 0x50400013, 0xac800000, 0x8002eff, 0x0, 0x8ee24e20, 
+0x240c0040, 0x24420001, 0x504c0003, 0x1021, 0x8ee24e20, 0x24420001, 
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020012, 
+0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204d4, 
+0x3c040001, 0x24844b14, 0xafa00014, 0xafa20010, 0x8ee605f8, 0x8f470228, 
+0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x16000003, 
+0x240c0001, 0x8002f4c, 0xa2ec04e4, 0x8ee2016c, 0x24420001, 0xaee2016c, 
+0x8ee2016c, 0x8ee204d4, 0xa2e004e4, 0xaee004e0, 0xaee07264, 0xaee204e8, 
+0x8f42023c, 0x10400030, 0x0, 0x8ee20180, 0x24420001, 0xaee20180, 
+0x8002f4c, 0x8ee20180, 0x8ee204f4, 0x240c0040, 0x24420001, 0x504c0003, 
+0x1021, 0x8ee204f4, 0x24420001, 0xaee204f4, 0x8ee204f4, 0x8e630018, 
+0x240c0003, 0x21080, 0x571021, 0x146c000f, 0x8c4404f8, 0x3c020001, 
+0x571021, 0x904283a1, 0x10400014, 0x0, 0x8ee201c8, 0x8ee35230, 
+0x441021, 0xaee201c8, 0x8ee201cc, 0x641821, 0x306300ff, 0x8002f47, 
+0xaee35230, 0x8ee201c4, 0x8ee30e00, 0x441021, 0xaee201c4, 0x8ee201cc, 
+0x641821, 0x306301ff, 0xaee30e00, 0x441021, 0xaee201cc, 0x8ee20000, 
+0x34420040, 0xaee20000, 0x8f820108, 0x24420020, 0xaf820108, 0x8f820108, 
+0x8f820108, 0x27633000, 0x43102b, 0x14400002, 0x27622800, 0xaf820108, 
+0x8f830108, 0x8f820104, 0x1462fc26, 0x0, 0x8fbf0060, 0x8fbe005c, 
+0x8fb60058, 0x8fb50054, 0x8fb40050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 
+0x8fb00040, 0x3e00008, 0x27bd0068, 0x52843, 0x10a0000d, 0x3021, 
+0x3c030001, 0x34633800, 0x3c07ffff, 0x3631021, 0x82102b, 0x50400001, 
+0x872021, 0x94820000, 0x24840002, 0x24a5ffff, 0x14a0fff8, 0xc23021, 
+0x61c02, 0x30c2ffff, 0x623021, 0x61c02, 0x30c2ffff, 0x623021, 
+0x3e00008, 0x30c2ffff, 0x27bdff88, 0x240f0001, 0xafbf0070, 0xafbe006c, 
 0xafb60068, 0xafb50064, 0xafb40060, 0xafb3005c, 0xafb20058, 0xafb10054, 
 0xafb00050, 0xa3a00027, 0xafaf002c, 0x8ee204c4, 0x8021, 0x30420001, 
 0x1440002a, 0xa3a00037, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023, 
@@ -1344,30 +1366,30 @@
 0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023, 
 0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821, 
 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 
-0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x8003429, 
+0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x80034bc, 
 0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0, 
 0x3c140001, 0x297a021, 0x8e9483b4, 0x3c130001, 0x2779821, 0x8e7383b8, 
-0x3c120001, 0x2579021, 0x80030ff, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 
+0x3c120001, 0x2579021, 0x8003183, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 
 0x10430007, 0x8821, 0x8f8200e4, 0x24110001, 0x8c430000, 0x8c440004, 
 0xafa30018, 0xafa4001c, 0x1620000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, 
-0x8f8200c8, 0x3c040001, 0x248449d0, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 
-0x3c050006, 0xc0023a7, 0x34a5f000, 0x8003429, 0x0, 0x8fa3001c, 
+0x8f8200c8, 0x3c040001, 0x24844be0, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 
+0x3c050006, 0xc002403, 0x34a5f000, 0x80034bc, 0x0, 0x8fa3001c, 
 0x8fb20018, 0x3074ffff, 0x2694fffc, 0x621024, 0x10400058, 0x2409821, 
 0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001, 
-0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x8003423, 
+0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x80034b6, 
 0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008, 
 0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080, 
 0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0, 
-0x106b0011, 0x0, 0x106a0015, 0x0, 0x8002fb5, 0x42042, 
+0x106b0011, 0x0, 0x106a0015, 0x0, 0x8003039, 0x42042, 
 0x10650023, 0xa3102b, 0x14400005, 0x0, 0x10690019, 0x0, 
-0x8002fb5, 0x42042, 0x10680021, 0x0, 0x8002fb5, 0x42042, 
-0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x8002fb5, 0x42042, 
-0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8002fb5, 0x42042, 
-0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x8002fb5, 0x42042, 
-0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x8002fb5, 0x42042, 
-0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x8002fb5, 0x42042, 
-0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x1087046d, 
-0x0, 0x8002f7a, 0x0, 0x3c020001, 0x571021, 0x904283a2, 
+0x8003039, 0x42042, 0x10680021, 0x0, 0x8003039, 0x42042, 
+0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x8003039, 0x42042, 
+0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8003039, 0x42042, 
+0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x8003039, 0x42042, 
+0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x8003039, 0x42042, 
+0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x8003039, 0x42042, 
+0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x1087047c, 
+0x0, 0x8002ffe, 0x0, 0x3c020001, 0x571021, 0x904283a2, 
 0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f, 
 0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005, 
 0x24100001, 0x96430004, 0x3402ffff, 0x10620075, 0x0, 0x92e204c8, 
@@ -1376,20 +1398,20 @@
 0x2821, 0x96660000, 0x520c0, 0x971021, 0x9442776e, 0x14460009, 
 0x971021, 0x94437770, 0x96620002, 0x14620005, 0x971021, 0x94437772, 
 0x96620004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400431, 
-0x0, 0x8003041, 0x0, 0x2402021, 0xc00229d, 0x24050006, 
-0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x14400425, 
+0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400440, 
+0x0, 0x80030c5, 0x0, 0x2402021, 0xc0022f8, 0x24050006, 
+0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x14400434, 
 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, 0xb71021, 
 0x94437270, 0x96620002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, 
 0x96620004, 0x10620035, 0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 
-0x14400412, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 0xb71021, 
-0x9442736e, 0x8003023, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, 
+0x14400421, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 0xb71021, 
+0x9442736e, 0x80030a7, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, 
 0x2e41021, 0x944b736c, 0x30638000, 0x14600010, 0xb28c0, 0xb71021, 
 0x9442736e, 0x1447fff5, 0x1602021, 0xb71021, 0x94437370, 0x96620002, 
 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96620004, 0x5462ffec, 
-0x420c0, 0x24060001, 0x30c200ff, 0x104003f1, 0x0, 0x8003041, 
-0x0, 0x97430202, 0x96420000, 0x146203eb, 0x0, 0x97430204, 
-0x96420002, 0x146203e7, 0x0, 0x97430206, 0x96420004, 0x146203e3, 
+0x420c0, 0x24060001, 0x30c200ff, 0x10400400, 0x0, 0x80030c5, 
+0x0, 0x97430202, 0x96420000, 0x146203fa, 0x0, 0x97430204, 
+0x96420002, 0x146203f6, 0x0, 0x97430206, 0x96420004, 0x146203f2, 
 0x0, 0x92420000, 0x3a030001, 0x30420001, 0x431024, 0x10400074, 
 0x2402ffff, 0x8e630000, 0x14620004, 0x3402ffff, 0x96630004, 0x1062006f, 
 0x240f0002, 0x3c020001, 0x571021, 0x904283a2, 0x1440006a, 0x240f0003, 
@@ -1399,33 +1421,33 @@
 0x14460009, 0x971021, 0x94437770, 0x96620002, 0x14620005, 0x971021, 
 0x94437772, 0x96620004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 
 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 
-0x14400044, 0x240f0003, 0x8003423, 0x0, 0x2402021, 0xc00229d, 
+0x14400044, 0x240f0003, 0x80034b6, 0x0, 0x2402021, 0xc0022f8, 
 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 
-0x144003a0, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, 
+0x144003af, 0xb71021, 0x9443726e, 0x96620000, 0x1462000b, 0x418c0, 
 0xb71021, 0x94437270, 0x96620002, 0x14620006, 0x418c0, 0xb71021, 
 0x94437272, 0x96620004, 0x10620027, 0x418c0, 0x2e31021, 0x9442726c, 
-0x30428000, 0x1440038d, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 
-0xb71021, 0x9442736e, 0x80030a8, 0x3021, 0x420c0, 0x2e41021, 
+0x30428000, 0x1440039c, 0x2e31021, 0x944b726c, 0x96670000, 0xb28c0, 
+0xb71021, 0x9442736e, 0x800312c, 0x3021, 0x420c0, 0x2e41021, 
 0x9443736c, 0x2e41021, 0x944b736c, 0x30638000, 0x14600010, 0xb28c0, 
 0xb71021, 0x9442736e, 0x1447fff5, 0x1602021, 0xb71021, 0x94437370, 
 0x96620002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96620004, 
-0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x1040036c, 0x0, 
-0x80030bb, 0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260, 0x54102b, 
+0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x1040037b, 0x0, 
+0x800313f, 0x240f0003, 0x240f0001, 0xafaf002c, 0x8f420260, 0x54102b, 
 0x1040003a, 0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 
 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2801821, 0x1021, 
 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 
 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 
 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 
-0x248449d8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc0023a7, 
-0x34a5f003, 0x8003429, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, 
-0x3c040001, 0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006, 
-0xc0023a7, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, 
-0x8ee301bc, 0x2403ffbf, 0x431024, 0x80033cd, 0xaee20000, 0x96e20468, 
-0x54102b, 0x10400003, 0x0, 0x240f0001, 0xa3af0027, 0x128002f2, 
+0x24844be8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 
+0x34a5f003, 0x80034bc, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, 
+0x3c040001, 0x24844bf4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006, 
+0xc002403, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, 
+0x8ee301bc, 0x2403ffbf, 0x431024, 0x8003460, 0xaee20000, 0x96e20468, 
+0x54102b, 0x10400003, 0x0, 0x240f0001, 0xa3af0027, 0x12800301, 
 0x24160007, 0x24150040, 0x241e0001, 0x240e0012, 0x8ee2723c, 0x8f430280, 
-0x24420001, 0x304203ff, 0x106202c4, 0x0, 0x93a20027, 0x10400014, 
+0x24420001, 0x304203ff, 0x106202d3, 0x0, 0x93a20027, 0x10400014, 
 0x0, 0x8ee35230, 0x8ee25234, 0x10620009, 0x26ed5234, 0x8ee65234, 
-0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x800312b, 
+0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x80031af, 
 0x306b00ff, 0x92e27238, 0x1440ffca, 0x0, 0x8ee201d0, 0x24420001, 
 0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffc2, 0x26ed0e08, 
 0x8ee60e08, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28021, 0x24630001, 
@@ -1439,28 +1461,29 @@
 0x439823, 0x26820007, 0x2404fff8, 0x9603000a, 0x446024, 0x6a1821, 
 0x6c102b, 0x10400002, 0x1803821, 0x603821, 0xae130018, 0x8f880120, 
 0x24e20007, 0x443824, 0x27623800, 0x25090020, 0x122102b, 0x50400001, 
-0x27693000, 0x8f820128, 0x15220007, 0x1401821, 0x8ee201a0, 0x8821, 
-0x24420001, 0xaee201a0, 0x80031b5, 0x8ee201a0, 0x8e040000, 0x8e050004, 
-0x1021, 0xad130008, 0xa507000e, 0xad160018, 0xad06001c, 0xa3302b, 
-0xa32823, 0x822023, 0x862023, 0xad040000, 0xad050004, 0x8ee204b0, 
-0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0, 
-0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 
-0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0, 
-0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80031a2, 0x0, 
-0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80031b5, 0x0, 
-0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001, 
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac960000, 
-0xac9e0004, 0x16200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x248449f0, 
-0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc0023a7, 
-0xafa30014, 0x93a20037, 0x1040020a, 0x340f8100, 0x8e420004, 0x8e430008, 
-0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004, 0xae440008, 0x96020016, 
-0x80033cd, 0xa642000e, 0x14ec015f, 0x28a1823, 0x960c000a, 0x9603000e, 
-0x28a1023, 0xa602000a, 0x34620004, 0xa602000e, 0x8f880120, 0x27623800, 
-0x25090020, 0x122102b, 0x14400002, 0x306affff, 0x27693000, 0x8f820128, 
+0x27693000, 0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007, 
+0x1401821, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 0x800323c, 
+0x8ee201a0, 0x8e040000, 0x8e050004, 0x1021, 0xad130008, 0xa507000e, 
+0xad160018, 0xad06001c, 0xa3302b, 0xa32823, 0x822023, 0x862023, 
+0xad040000, 0xad050004, 0x8ee204b0, 0xad020010, 0xaf890120, 0x92e24e10, 
+0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
+0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
+0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
+0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
+0x0, 0x8003229, 0x0, 0x14600005, 0x0, 0x8f820128, 
+0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
+0xac800000, 0x800323c, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x16200018, 0x3c050006, 
+0x8e020018, 0x3c040001, 0x24844c00, 0xafa20010, 0x8e020000, 0x8e030004, 
+0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x93a20037, 0x10400216, 
+0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, 
+0xae430004, 0xae440008, 0x96020016, 0x8003460, 0xa642000e, 0x14ec0168, 
+0x28a1823, 0x960c000a, 0x9603000e, 0x28a1023, 0xa602000a, 0x34620004, 
+0xa602000e, 0x8f880120, 0x27623800, 0x25090020, 0x122102b, 0x14400002, 
+0x306affff, 0x27693000, 0x8f820128, 0x11220004, 0x0, 0x8f820124, 
 0x15220007, 0x24040020, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 
-0x8003230, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e, 
+0x80032ba, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e, 
 0x24040004, 0xad100008, 0xad040018, 0x52940, 0xa01821, 0x1021, 
 0xe33821, 0xe3202b, 0xc23021, 0xc43021, 0xad060000, 0xad070004, 
 0x8ee2723c, 0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 
@@ -1468,278 +1491,280 @@
 0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
 0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x800321d, 0x0, 0x14600005, 0x0, 0x8f820128, 
+0x0, 0x80032a7, 0x0, 0x14600005, 0x0, 0x8f820128, 
 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
-0xac800000, 0x8003230, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 
+0xac800000, 0x80032ba, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 
 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
 0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620000d, 0x0, 
 0xa60c000a, 0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 
-0x248449fc, 0x3c050006, 0xafa20014, 0x8ee6723c, 0x8003398, 0x34a5f00b, 
+0x24844c0c, 0x3c050006, 0xafa20014, 0x8ee6723c, 0x800342b, 0x34a5f00b, 
 0x3c010001, 0x370821, 0xa02083b0, 0xadab0000, 0x8ee201cc, 0x8ee3723c, 
 0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x24630001, 0x306303ff, 0x26e25234, 
-0x15a20006, 0xaee3723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003255, 
+0x15a20006, 0xaee3723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x80032df, 
 0x8ee201c8, 0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8f420240, 
-0x10400070, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240, 
-0x43102b, 0x1440016d, 0xa021, 0x8f830120, 0x27623800, 0x24660020, 
-0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 0x0, 
-0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 0x80032b2, 0x8ee201a0, 
-0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 0xac620008, 
-0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 0xac650004, 
-0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24110001, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x144e001f, 
-0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 
-0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x800329f, 
-0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80032b2, 
-0x0, 0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 
-0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001, 0x8ee2723c, 0x3c040001, 
-0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 
-0x34a5f008, 0xc0023a7, 0xafae0048, 0x8fae0048, 0x56200001, 0xaee00e0c, 
-0x8ee20184, 0x24420001, 0xaee20184, 0x8003328, 0x8ee20184, 0x8f830120, 
-0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 
+0x10400073, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240, 
+0x43102b, 0x14400176, 0xa021, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001, 
+0xaee201a0, 0x800333f, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 
+0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
+0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
+0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
+0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
+0x8ee34e20, 0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 
+0x10620005, 0x0, 0x800332c, 0x0, 0x14600005, 0x0, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
+0x50400010, 0xac800000, 0x800333f, 0x0, 0x8ee24e20, 0x24420001, 
+0x50550003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x5620000d, 
+0x24110001, 0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 
+0x8ee6723c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 
+0x8fae0048, 0x56200001, 0xaee00e0c, 0x8ee20184, 0x24420001, 0xaee20184, 
+0x80033b8, 0x8ee20184, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 
 0x14c20007, 0x0, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 
-0x800331a, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 
+0x80033aa, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 
 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 
 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 
 0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8003307, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
-0xac800000, 0x800331a, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0, 
-0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, 
-0x8f470280, 0x3c050009, 0x34a5f008, 0xc0023a7, 0xafae0048, 0x8fae0048, 
-0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x80033cb, 0xa021, 
-0x960c000a, 0x183102b, 0x54400001, 0x1801821, 0xa603000a, 0x8f880120, 
-0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, 
-0x15220007, 0x24040020, 0x8ee201a0, 0x8821, 0x24420001, 0xaee201a0, 
-0x800338c, 0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xa504000e, 
-0x24040004, 0xad100008, 0xad040018, 0x52940, 0xa01821, 0x1021, 
-0xe33821, 0xe3202b, 0xc23021, 0xc43021, 0xad060000, 0xad070004, 
-0x8ee2723c, 0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 
-0x14400033, 0x24110001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0x8c820000, 0x1456001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
+0x8c820000, 0x144e001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
 0x24420001, 0x10550007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8003379, 0x0, 0x14600005, 0x0, 0x8f820128, 
+0x0, 0x8003397, 0x0, 0x14600005, 0x0, 0x8f820128, 
 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
-0xac800000, 0x800338c, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 
+0xac800000, 0x80033aa, 0x0, 0x8ee24e20, 0x24420001, 0x50550003, 
 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620001d, 0x0, 
-0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x248449fc, 
-0x3c050006, 0xafa20014, 0x8ee6723c, 0x34a5f00d, 0xc0023a7, 0x2003821, 
-0x93a20037, 0x10400031, 0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, 
-0xa64f000c, 0xae420000, 0xae430004, 0xae440008, 0x96020016, 0xa642000e, 
-0x9602000e, 0x3042fdff, 0x80033cd, 0xa602000e, 0x8ee201cc, 0x2442ffff, 
-0xaee201cc, 0x8ee201cc, 0x8ee201c4, 0x3c04001f, 0x3c010001, 0x370821, 
-0xa03e83b0, 0x2442ffff, 0xaee201c4, 0x9603000a, 0x3484ffff, 0x8ee201c4, 
-0x6a1821, 0x2639821, 0x93202b, 0x10800003, 0x3c02fff5, 0x34421000, 
-0x2629821, 0xadab0000, 0x8ee2723c, 0x24420001, 0x304203ff, 0xaee2723c, 
-0x8f420240, 0x10400004, 0x283a023, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 
-0xa3a00027, 0x1680fd38, 0x0, 0x12800024, 0x0, 0x3c010001, 
-0x370821, 0xac3483b4, 0x3c010001, 0x370821, 0xac3383b8, 0x3c010001, 
-0x370821, 0xac3283bc, 0x93a20037, 0x10400008, 0x0, 0x3c020001, 
-0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 0xac2283bc, 
-0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x14620006, 0x0, 
-0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003429, 0x8ee201c0, 0x8ee201b8, 
-0x24420001, 0xaee201b8, 0x8003429, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 
-0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 
-0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8faf002c, 0x24020002, 
-0x11e2000f, 0x29e20003, 0x14400017, 0x24020003, 0x15e20015, 0x0, 
-0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001, 0x441021, 0xaee200d0, 
-0xaee300d4, 0x8ee200d0, 0x8003423, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 
-0x24630001, 0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, 
-0x8003423, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, 
-0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 
-0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0070, 
-0x8fbe006c, 0x8fb60068, 0x8fb50064, 0x8fb40060, 0x8fb3005c, 0x8fb20058, 
-0x8fb10054, 0x8fb00050, 0x3e00008, 0x27bd0078, 0x27bdffb0, 0xafb50044, 
-0xa821, 0xafb00030, 0x8021, 0xafbf004c, 0xafb60048, 0xafb40040, 
-0xafb3003c, 0xafb20038, 0xafb10034, 0x8ee204c4, 0x24140001, 0x30420001, 
-0x1440002a, 0xb021, 0x8f8700e0, 0x8f8800c4, 0x8f8200e8, 0xe22023, 
-0x2c821000, 0x50400001, 0x24841000, 0x420c2, 0x801821, 0x8ee400c8, 
-0x8ee500cc, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
-0xaee400c8, 0xaee500cc, 0x8f8300c8, 0x3c02000a, 0x3442efff, 0x1032023, 
-0x44102b, 0x10400003, 0x3c02000a, 0x3442f000, 0x822021, 0x801821, 
-0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 
-0x862021, 0xaee400c0, 0xaee500c4, 0xaf8800c8, 0xaf8700e4, 0x80037aa, 
-0xaf8700e8, 0x3c020001, 0x571021, 0x904283b0, 0x1040000b, 0x0, 
-0x3c130001, 0x2779821, 0x8e7383b4, 0x3c110001, 0x2378821, 0x8e3183b8, 
-0x3c120001, 0x2579021, 0x8003645, 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 
-0x10430007, 0x4821, 0x8f8200e4, 0x24090001, 0x8c430000, 0x8c440004, 
-0xafa30018, 0xafa4001c, 0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, 
-0x8f8200c8, 0x3c040001, 0x248449d0, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 
-0x3c050006, 0xc0023a7, 0x34a5f000, 0x80037aa, 0x0, 0x8fa3001c, 
-0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, 0x10400058, 0x2408821, 
-0x3c020080, 0x621024, 0x1040000a, 0x3c040040, 0x8ee2007c, 0x24420001, 
-0xaee2007c, 0x8ee2007c, 0x8ee201ec, 0x24420001, 0xaee201ec, 0x80037a4, 
-0x8ee201ec, 0x3c060004, 0x3c0b0001, 0x3c0a0002, 0x3c050010, 0x3c090008, 
-0x8ee20080, 0x3c080020, 0x34078000, 0x24420001, 0xaee20080, 0x8ee20080, 
-0x8fa2001c, 0x441824, 0x10660021, 0xc3102b, 0x14400007, 0x0, 
-0x106b0011, 0x0, 0x106a0015, 0x0, 0x80034ef, 0x42042, 
-0x10650023, 0xa3102b, 0x14400005, 0x0, 0x10690019, 0x0, 
-0x80034ef, 0x42042, 0x10680021, 0x0, 0x80034ef, 0x42042, 
-0x8ee20034, 0x24420001, 0xaee20034, 0x8ee20034, 0x80034ef, 0x42042, 
-0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x80034ef, 0x42042, 
-0x8ee201e0, 0x24420001, 0xaee201e0, 0x8ee201e0, 0x80034ef, 0x42042, 
-0x8ee201e4, 0x24420001, 0xaee201e4, 0x8ee201e4, 0x80034ef, 0x42042, 
-0x8ee20030, 0x24420001, 0xaee20030, 0x8ee20030, 0x80034ef, 0x42042, 
-0x8ee201e8, 0x24420001, 0xaee201e8, 0x8ee201e8, 0x42042, 0x108702b4, 
-0x0, 0x80034b4, 0x0, 0x3c020001, 0x571021, 0x904283a2, 
-0x14400084, 0x24020001, 0x3c030001, 0x771821, 0x906383a3, 0x1462007f, 
-0x3c020100, 0x8e430000, 0x621024, 0x1040006f, 0x2402ffff, 0x14620005, 
-0x24100001, 0x96430004, 0x3402ffff, 0x10620075, 0x0, 0x92e204c8, 
-0x14400072, 0x0, 0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 
-0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 
-0x2821, 0x96260000, 0x520c0, 0x971021, 0x9442776e, 0x14460009, 
-0x971021, 0x94437770, 0x96220002, 0x14620005, 0x971021, 0x94437772, 
-0x96220004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 
-0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 0x10400278, 
-0x0, 0x800357b, 0x0, 0x2402021, 0xc00229d, 0x24050006, 
-0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 0x1440026c, 
-0xb71021, 0x9443726e, 0x96220000, 0x1462000b, 0x418c0, 0xb71021, 
-0x94437270, 0x96220002, 0x14620006, 0x418c0, 0xb71021, 0x94437272, 
-0x96220004, 0x10620035, 0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 
-0x14400259, 0x2e31021, 0x9448726c, 0x96270000, 0x828c0, 0xb71021, 
-0x9442736e, 0x800355d, 0x3021, 0x420c0, 0x2e41021, 0x9443736c, 
-0x2e41021, 0x9448736c, 0x30638000, 0x14600010, 0x828c0, 0xb71021, 
-0x9442736e, 0x1447fff5, 0x1002021, 0xb71021, 0x94437370, 0x96220002, 
-0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96220004, 0x5462ffec, 
-0x420c0, 0x24060001, 0x30c200ff, 0x10400238, 0x0, 0x800357b, 
-0x0, 0x97430202, 0x96420000, 0x14620232, 0x0, 0x97430204, 
-0x96420002, 0x1462022e, 0x0, 0x97430206, 0x96420004, 0x1462022a, 
-0x0, 0x92420000, 0x3a030001, 0x30420001, 0x431024, 0x10400074, 
-0x2402ffff, 0x8e230000, 0x14620004, 0x3402ffff, 0x96230004, 0x1062006f, 
-0x24140002, 0x3c020001, 0x571021, 0x904283a2, 0x1440006a, 0x24140003, 
-0x92e204c8, 0x14400067, 0x0, 0x3c020001, 0x571021, 0x8c4283a4, 
-0x28420005, 0x10400020, 0x3821, 0x3c020001, 0x571021, 0x8c4283a4, 
-0x18400016, 0x2821, 0x96260000, 0x520c0, 0x971021, 0x9442776e, 
-0x14460009, 0x971021, 0x94437770, 0x96220002, 0x14620005, 0x971021, 
-0x94437772, 0x96220004, 0x50620008, 0x24070001, 0x3c020001, 0x571021, 
-0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 0x520c0, 0x30e200ff, 
-0x14400044, 0x24140003, 0x80037a4, 0x0, 0x2402021, 0xc00229d, 
-0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 0x9442726c, 0x30424000, 
-0x144001e7, 0xb71021, 0x9443726e, 0x96220000, 0x1462000b, 0x418c0, 
-0xb71021, 0x94437270, 0x96220002, 0x14620006, 0x418c0, 0xb71021, 
-0x94437272, 0x96220004, 0x10620027, 0x418c0, 0x2e31021, 0x9442726c, 
-0x30428000, 0x144001d4, 0x2e31021, 0x9448726c, 0x96270000, 0x828c0, 
-0xb71021, 0x9442736e, 0x80035e2, 0x3021, 0x420c0, 0x2e41021, 
-0x9443736c, 0x2e41021, 0x9448736c, 0x30638000, 0x14600010, 0x828c0, 
-0xb71021, 0x9442736e, 0x1447fff5, 0x1002021, 0xb71021, 0x94437370, 
-0x96220002, 0x5462fff1, 0x420c0, 0xb71021, 0x94437372, 0x96220004, 
-0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 0x104001b3, 0x0, 
-0x80035f5, 0x24140003, 0x24140001, 0x8f420260, 0x53102b, 0x10400049, 
-0x0, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 
-0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 0x2601821, 0x1021, 0xa32821, 
-0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 
-0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 
-0x8ee2007c, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 0x248449d8, 
-0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc0023a7, 0x34a5f003, 
-0x80037aa, 0x0, 0x8ee25230, 0xafa20010, 0x8ee25234, 0x3c040001, 
-0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0xc0023a7, 0x34a5f002, 
-0x8ee201bc, 0x24420001, 0xaee201bc, 0x8ee20000, 0x8ee301bc, 0x2403ffbf, 
-0x431024, 0x8003752, 0xaee20000, 0x8ee25230, 0xafa20010, 0x8ee25234, 
-0x3c040001, 0x248449e4, 0xafa20014, 0x8ee60e00, 0x8ee70e08, 0x3c050006, 
-0xc0023a7, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 0x8003752, 
-0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, 0x3c158000, 0x1260012e, 
-0x3c0c001f, 0x358cffff, 0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 
-0x10620105, 0x0, 0x12a00014, 0x0, 0x8ee35230, 0x8ee25234, 
-0x10620009, 0x26ee5234, 0x8eeb5234, 0x8ee35234, 0x21140, 0x24425238, 
-0x2e28021, 0x24630001, 0x800366f, 0x306800ff, 0x92e27238, 0x1440ffc0, 
-0x3c050006, 0x8ee201d0, 0x24420001, 0xaee201d0, 0x8ee201d0, 0x8ee30e00, 
-0x8ee20e08, 0x1062ffcb, 0x26ee0e08, 0x8eeb0e08, 0xa821, 0x8ee30e08, 
-0x21140, 0x24420e10, 0x2e28021, 0x24630001, 0x306801ff, 0x96e2046a, 
-0x30420010, 0x10400017, 0x34028100, 0x9643000c, 0x14620014, 0x0, 
-0x3c020001, 0x571021, 0x904283b0, 0x1440000f, 0x0, 0x9642000e, 
-0xa6020016, 0x8e420008, 0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c, 
-0xae430008, 0xae440004, 0x9602000e, 0x26310004, 0x24160001, 0x34420200, 
-0xa602000e, 0x9603000a, 0x2605021, 0x73102b, 0x10400002, 0x2606821, 
-0x605021, 0x2d42003d, 0x1040002a, 0x3821, 0x9623000c, 0x24020800, 
-0x54620027, 0xae110018, 0x3c020001, 0x571021, 0x904283b0, 0x54400022, 
-0xae110018, 0x26220017, 0x182102b, 0x10400013, 0x0, 0x3c02fff5, 
-0x511021, 0x90421017, 0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 
-0x621825, 0x10600013, 0x26220010, 0x182102b, 0x1040000e, 0x0, 
-0x3c07fff5, 0xf13821, 0x94e71010, 0x80036bb, 0x24e7000e, 0x92220017, 
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600004, 
-0xae110018, 0x96270010, 0x24e7000e, 0xae110018, 0x3c020001, 0x571021, 
-0x904283b0, 0x2102b, 0x14e00002, 0x24ec0, 0x1403821, 0x8f830120, 
-0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 
+0x24425028, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0, 
+0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 0x8ee6723c, 
+0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048, 
+0x8ee20170, 0x24420001, 0xaee20170, 0x8ee20170, 0x800345e, 0xa021, 
+0x960c000a, 0x183102b, 0x54400001, 0x1801821, 0xa603000a, 0x8f880120, 
+0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, 
+0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020, 0x8ee201a0, 
+0x8821, 0x24420001, 0xaee201a0, 0x800341f, 0x8ee201a0, 0x8ee5723c, 
+0x8ee60480, 0x8ee70484, 0xa504000e, 0x24040004, 0xad100008, 0xad040018, 
+0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021, 
+0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0xad02001c, 0x8ee204b4, 
+0xad020010, 0xaf890120, 0x92e24e10, 0x14400033, 0x24110001, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1456001f, 0x0, 
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 
+0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10550007, 0x0, 
+0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x800340c, 0x0, 
+0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
+0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x800341f, 0x0, 
+0x8ee24e20, 0x24420001, 0x50550003, 0x1021, 0x8ee24e20, 0x24420001, 
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac960000, 
+0xac9e0004, 0x1620001d, 0x0, 0xa60c000a, 0x8f820100, 0xafa20010, 
+0x8f820104, 0x3c040001, 0x24844c0c, 0x3c050006, 0xafa20014, 0x8ee6723c, 
+0x34a5f00d, 0xc002403, 0x2003821, 0x93a20037, 0x10400031, 0x340f8100, 
+0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, 0xae430004, 
+0xae440008, 0x96020016, 0xa642000e, 0x9602000e, 0x3042fdff, 0x8003460, 
+0xa602000e, 0x8ee201cc, 0x2442ffff, 0xaee201cc, 0x8ee201cc, 0x8ee201c4, 
+0x3c04001f, 0x3c010001, 0x370821, 0xa03e83b0, 0x2442ffff, 0xaee201c4, 
+0x9603000a, 0x3484ffff, 0x8ee201c4, 0x6a1821, 0x2639821, 0x93202b, 
+0x10800003, 0x3c02fff5, 0x34421000, 0x2629821, 0xadab0000, 0x8ee2723c, 
+0x24420001, 0x304203ff, 0xaee2723c, 0x8f420240, 0x10400004, 0x283a023, 
+0x8ee20e0c, 0x24420001, 0xaee20e0c, 0xa3a00027, 0x1680fd29, 0x0, 
+0x12800024, 0x0, 0x3c010001, 0x370821, 0xac3483b4, 0x3c010001, 
+0x370821, 0xac3383b8, 0x3c010001, 0x370821, 0xac3283bc, 0x93a20037, 
+0x10400008, 0x0, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, 
+0x3c010001, 0x370821, 0xac2283bc, 0x8ee2723c, 0x8f430280, 0x24420001, 
+0x304203ff, 0x14620006, 0x0, 0x8ee201c0, 0x24420001, 0xaee201c0, 
+0x80034bc, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, 0x80034bc, 
+0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4, 
+0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 
+0xaee500c4, 0x8faf002c, 0x24020002, 0x11e2000f, 0x29e20003, 0x14400017, 
+0x24020003, 0x15e20015, 0x0, 0x8ee200d0, 0x8ee300d4, 0x24630001, 
+0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x80034b6, 
+0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 0x441021, 
+0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x80034b6, 0x8ee300dc, 0x8ee200c8, 
+0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 0xaee300cc, 
+0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 
+0xaf8300e4, 0xaf8300e8, 0x8fbf0070, 0x8fbe006c, 0x8fb60068, 0x8fb50064, 
+0x8fb40060, 0x8fb3005c, 0x8fb20058, 0x8fb10054, 0x8fb00050, 0x3e00008, 
+0x27bd0078, 0x27bdffb0, 0xafb50044, 0xa821, 0xafb00030, 0x8021, 
+0xafbf004c, 0xafb60048, 0xafb40040, 0xafb3003c, 0xafb20038, 0xafb10034, 
+0x8ee204c4, 0x24140001, 0x30420001, 0x1440002a, 0xb021, 0x8f8700e0, 
+0x8f8800c4, 0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001, 0x24841000, 
+0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc, 0x1021, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8, 
+0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a, 
+0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 
+0xaf8800c8, 0xaf8700e4, 0x8003840, 0xaf8700e8, 0x3c020001, 0x571021, 
+0x904283b0, 0x1040000b, 0x0, 0x3c130001, 0x2779821, 0x8e7383b4, 
+0x3c110001, 0x2378821, 0x8e3183b8, 0x3c120001, 0x2579021, 0x80036d8, 
+0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x4821, 0x8f8200e4, 
+0x24090001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1520000e, 
+0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844be0, 
+0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000, 
+0x8003840, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 
+0x621024, 0x10400058, 0x2408821, 0x3c020080, 0x621024, 0x1040000a, 
+0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8ee201ec, 
+0x24420001, 0xaee201ec, 0x800383a, 0x8ee201ec, 0x3c060004, 0x3c0b0001, 
+0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000, 
+0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021, 
+0xc3102b, 0x14400007, 0x0, 0x106b0011, 0x0, 0x106a0015, 
+0x0, 0x8003582, 0x42042, 0x10650023, 0xa3102b, 0x14400005, 
+0x0, 0x10690019, 0x0, 0x8003582, 0x42042, 0x10680021, 
+0x0, 0x8003582, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034, 
+0x8ee20034, 0x8003582, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc, 
+0x8ee201dc, 0x8003582, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0, 
+0x8ee201e0, 0x8003582, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4, 
+0x8ee201e4, 0x8003582, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030, 
+0x8ee20030, 0x8003582, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8, 
+0x8ee201e8, 0x42042, 0x108702b7, 0x0, 0x8003547, 0x0, 
+0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001, 
+0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024, 
+0x1040006f, 0x2402ffff, 0x14620005, 0x24100001, 0x96430004, 0x3402ffff, 
+0x10620075, 0x0, 0x92e204c8, 0x14400072, 0x0, 0x3c020001, 
+0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, 0x3c020001, 
+0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96260000, 0x520c0, 
+0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96220002, 
+0x14620005, 0x971021, 0x94437772, 0x96220004, 0x50620008, 0x24070001, 
+0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 
+0x520c0, 0x30e200ff, 0x1040027b, 0x0, 0x800360e, 0x0, 
+0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 
+0x9442726c, 0x30424000, 0x1440026f, 0xb71021, 0x9443726e, 0x96220000, 
+0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96220002, 0x14620006, 
+0x418c0, 0xb71021, 0x94437272, 0x96220004, 0x10620035, 0x418c0, 
+0x2e31021, 0x9442726c, 0x30428000, 0x1440025c, 0x2e31021, 0x9448726c, 
+0x96270000, 0x828c0, 0xb71021, 0x9442736e, 0x80035f0, 0x3021, 
+0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x9448736c, 0x30638000, 
+0x14600010, 0x828c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1002021, 
+0xb71021, 0x94437370, 0x96220002, 0x5462fff1, 0x420c0, 0xb71021, 
+0x94437372, 0x96220004, 0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 
+0x1040023b, 0x0, 0x800360e, 0x0, 0x97430202, 0x96420000, 
+0x14620235, 0x0, 0x97430204, 0x96420002, 0x14620231, 0x0, 
+0x97430206, 0x96420004, 0x1462022d, 0x0, 0x92420000, 0x3a030001, 
+0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e230000, 0x14620004, 
+0x3402ffff, 0x96230004, 0x1062006f, 0x24140002, 0x3c020001, 0x571021, 
+0x904283a2, 0x1440006a, 0x24140003, 0x92e204c8, 0x14400067, 0x0, 
+0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, 
+0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96260000, 
+0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 
+0x96220002, 0x14620005, 0x971021, 0x94437772, 0x96220004, 0x50620008, 
+0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 
+0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24140003, 0x800383a, 
+0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 
+0x2e51021, 0x9442726c, 0x30424000, 0x144001ea, 0xb71021, 0x9443726e, 
+0x96220000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96220002, 
+0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96220004, 0x10620027, 
+0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x144001d7, 0x2e31021, 
+0x9448726c, 0x96270000, 0x828c0, 0xb71021, 0x9442736e, 0x8003675, 
+0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x9448736c, 
+0x30638000, 0x14600010, 0x828c0, 0xb71021, 0x9442736e, 0x1447fff5, 
+0x1002021, 0xb71021, 0x94437370, 0x96220002, 0x5462fff1, 0x420c0, 
+0xb71021, 0x94437372, 0x96220004, 0x5462ffec, 0x420c0, 0x24060001, 
+0x30c200ff, 0x104001b6, 0x0, 0x8003688, 0x24140003, 0x24140001, 
+0x8f420260, 0x53102b, 0x10400049, 0x0, 0x8f8300e4, 0x8f8200e0, 
+0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 
+0x2601821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
+0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 
+0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, 
+0x8f8200e4, 0x3c040001, 0x24844be8, 0xafa20014, 0x8fa60018, 0x8fa7001c, 
+0x3c050006, 0xc002403, 0x34a5f003, 0x8003840, 0x0, 0x8ee25230, 
+0xafa20010, 0x8ee25234, 0x3c040001, 0x24844bf4, 0xafa20014, 0x8ee60e00, 
+0x8ee70e08, 0xc002403, 0x34a5f002, 0x8ee201bc, 0x24420001, 0xaee201bc, 
+0x8ee20000, 0x8ee301bc, 0x2403ffbf, 0x431024, 0x80037e8, 0xaee20000, 
+0x8ee25230, 0xafa20010, 0x8ee25234, 0x3c040001, 0x24844bf4, 0xafa20014, 
+0x8ee60e00, 0x8ee70e08, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201bc, 
+0x24420001, 0xaee201bc, 0x80037e8, 0x8ee201bc, 0x96e20468, 0x53102b, 
+0x54400001, 0x3c158000, 0x12600131, 0x3c0c001f, 0x358cffff, 0x8ee2723c, 
+0x8f430280, 0x24420001, 0x304203ff, 0x10620108, 0x0, 0x12a00014, 
+0x0, 0x8ee35230, 0x8ee25234, 0x10620009, 0x26ee5234, 0x8eeb5234, 
+0x8ee35234, 0x21140, 0x24425238, 0x2e28021, 0x24630001, 0x8003702, 
+0x306800ff, 0x92e27238, 0x1440ffc0, 0x3c050006, 0x8ee201d0, 0x24420001, 
+0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffcb, 0x26ee0e08, 
+0x8eeb0e08, 0xa821, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28021, 
+0x24630001, 0x306801ff, 0x96e2046a, 0x30420010, 0x10400017, 0x34028100, 
+0x9643000c, 0x14620014, 0x0, 0x3c020001, 0x571021, 0x904283b0, 
+0x1440000f, 0x0, 0x9642000e, 0xa6020016, 0x8e420008, 0x8e430004, 
+0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 0x9602000e, 
+0x26310004, 0x24160001, 0x34420200, 0xa602000e, 0x9603000a, 0x2605021, 
+0x73102b, 0x10400002, 0x2606821, 0x605021, 0x2d42003d, 0x1040002a, 
+0x3821, 0x9623000c, 0x24020800, 0x54620027, 0xae110018, 0x3c020001, 
+0x571021, 0x904283b0, 0x54400022, 0xae110018, 0x26220017, 0x182102b, 
+0x10400013, 0x0, 0x3c02fff5, 0x511021, 0x90421017, 0x38430006, 
+0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x10600013, 0x26220010, 
+0x182102b, 0x1040000e, 0x0, 0x3c07fff5, 0xf13821, 0x94e71010, 
+0x800374e, 0x24e7000e, 0x92220017, 0x38430006, 0x2c630001, 0x38420011, 
+0x2c420001, 0x621825, 0x50600004, 0xae110018, 0x96270010, 0x24e7000e, 
+0xae110018, 0x3c020001, 0x571021, 0x904283b0, 0x2102b, 0x14e00002, 
+0x24ec0, 0x1403821, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 
+0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 
 0x14c20007, 0x2402000b, 0x8ee201a0, 0x4821, 0x24420001, 0xaee201a0, 
-0x8003719, 0x8ee201a0, 0x8e040000, 0x8e050004, 0xac620018, 0x1751025, 
+0x80037af, 0x8ee201a0, 0x8e040000, 0x8e050004, 0xac620018, 0x1751025, 
 0x491025, 0xac710008, 0xa467000e, 0xac62001c, 0xac640000, 0xac650004, 
 0x8ee204b0, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400038, 0x24090001, 
 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 
 0x14620020, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001c, 0x0, 
 0x8c820004, 0x24420001, 0xac820004, 0x8ee34e24, 0x8ee54e20, 0x24020040, 
 0x24630001, 0x10620007, 0x0, 0x8ee24e24, 0x24420001, 0x10a20005, 
-0x0, 0x8003703, 0x0, 0x14a00005, 0x0, 0x8f820128, 
+0x0, 0x8003799, 0x0, 0x14a00005, 0x0, 0x8f820128, 
 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x8003719, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 
+0xac800000, 0x80037af, 0x0, 0x8ee24e20, 0x24030040, 0x24420001, 
 0x50430003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 
-0xac820004, 0x15200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x248449f0, 
-0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc0023a7, 
+0xac820004, 0x15200018, 0x3c050006, 0x8e020018, 0x3c040001, 0x24844c00, 
+0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403, 
 0xafa30014, 0x32c200ff, 0x1040002b, 0x34028100, 0x8e430004, 0x8e440008, 
 0x8e45000c, 0xa642000c, 0xae430000, 0xae440004, 0xae450008, 0x96020016, 
-0x8003752, 0xa642000e, 0x154d000a, 0x0, 0x9602000e, 0xa613000a, 
-0x34420004, 0xa602000e, 0x3c010001, 0x370821, 0xa02083b0, 0x8003750, 
+0x80037e8, 0xa642000e, 0x154d000a, 0x0, 0x9602000e, 0xa613000a, 
+0x34420004, 0xa602000e, 0x3c010001, 0x370821, 0xa02083b0, 0x80037e6, 
 0x9821, 0x9604000a, 0x93102b, 0x10400002, 0x2601821, 0x801821, 
 0x24020001, 0xa603000a, 0x3c010001, 0x370821, 0xa02283b0, 0x9604000a, 
 0x2248821, 0x191102b, 0x10400003, 0x3c02fff5, 0x34421000, 0x2228821, 
-0x2649823, 0xa821, 0x1660fef7, 0xadc80000, 0x12600021, 0x32c200ff, 
+0x2649823, 0xa821, 0x1660fef4, 0xadc80000, 0x12600021, 0x32c200ff, 
 0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 0x370821, 0xac3183b8, 
 0x3c010001, 0x370821, 0x10400008, 0xac3283bc, 0x3c020001, 0x571021, 
 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 0xac2283bc, 0x8ee2723c, 
 0x8f430280, 0x24420001, 0x14620006, 0x0, 0x8ee201c0, 0x24420001, 
-0xaee201c0, 0x80037aa, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, 
-0x80037aa, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, 
+0xaee201c0, 0x8003840, 0x8ee201c0, 0x8ee201b8, 0x24420001, 0xaee201b8, 
+0x8003840, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 0x8ee400c0, 
 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
 0x24020002, 0xaee400c0, 0xaee500c4, 0x1282000f, 0x2a820003, 0x14400017, 
 0x24020003, 0x16820015, 0x0, 0x8ee200d0, 0x8ee300d4, 0x24630001, 
-0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x80037a4, 
+0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 0x800383a, 
 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 0x441021, 
-0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x80037a4, 0x8ee300dc, 0x8ee200c8, 
+0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x800383a, 0x8ee300dc, 0x8ee200c8, 
 0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 0xaee300cc, 
 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 0x24630008, 
 0xaf8300e4, 0xaf8300e8, 0x8fbf004c, 0x8fb60048, 0x8fb50044, 0x8fb40040, 
 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 
-0x27bdff90, 0xafbe0064, 0xf021, 0xafbf0068, 0xafb60060, 0xafb5005c, 
+0x27bdff90, 0xafb60060, 0xb021, 0xafbf0068, 0xafbe0064, 0xafb5005c, 
 0xafb40058, 0xafb30054, 0xafb20050, 0xafb1004c, 0xafb00048, 0x8ee204c4, 
-0x8821, 0x24160001, 0x30420001, 0x1440002a, 0xa3a0002f, 0x8f8700e0, 
+0x8821, 0x24150001, 0x30420001, 0x1440002a, 0xa3a0002f, 0x8f8700e0, 
 0x8f8800c4, 0x8f8200e8, 0xe22023, 0x2c821000, 0x50400001, 0x24841000, 
 0x420c2, 0x801821, 0x8ee400c8, 0x8ee500cc, 0x1021, 0xa32821, 
 0xa3302b, 0x822021, 0x862021, 0xaee400c8, 0xaee500cc, 0x8f8300c8, 
 0x3c02000a, 0x3442efff, 0x1032023, 0x44102b, 0x10400003, 0x3c02000a, 
 0x3442f000, 0x822021, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 
 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xaee400c0, 0xaee500c4, 
-0xaf8800c8, 0xaf8700e4, 0x8003bb3, 0xaf8700e8, 0x3c020001, 0x571021, 
+0xaf8800c8, 0xaf8700e4, 0x8003c4b, 0xaf8700e8, 0x3c020001, 0x571021, 
 0x904283b0, 0x1040000b, 0x0, 0x3c130001, 0x2779821, 0x8e7383b4, 
-0x3c100001, 0x2178021, 0x8e1083b8, 0x3c120001, 0x2579021, 0x80039b3, 
+0x3c100001, 0x2178021, 0x8e1083b8, 0x3c120001, 0x2579021, 0x8003a49, 
 0x8e5283bc, 0x8f8300e0, 0x8f8200e4, 0x10430007, 0x3821, 0x8f8200e4, 
 0x24070001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x14e0000e, 
-0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844a14, 
-0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc0023a7, 0x34a5f200, 
-0x8003bb3, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 
+0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, 0x3c040001, 0x24844c24, 
+0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f200, 
+0x8003c4b, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 
 0x621024, 0x10400058, 0x2408021, 0x3c020080, 0x621024, 0x1040000a, 
 0x3c040040, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8ee201ec, 
-0x24420001, 0xaee201ec, 0x8003bad, 0x8ee201ec, 0x3c060004, 0x3c0b0001, 
+0x24420001, 0xaee201ec, 0x8003c45, 0x8ee201ec, 0x3c060004, 0x3c0b0001, 
 0x3c0a0002, 0x3c050010, 0x3c090008, 0x8ee20080, 0x3c080020, 0x34078000, 
 0x24420001, 0xaee20080, 0x8ee20080, 0x8fa2001c, 0x441824, 0x10660021, 
 0xc3102b, 0x14400007, 0x0, 0x106b0011, 0x0, 0x106a0015, 
-0x0, 0x8003870, 0x42042, 0x10650023, 0xa3102b, 0x14400005, 
-0x0, 0x10690019, 0x0, 0x8003870, 0x42042, 0x10680021, 
-0x0, 0x8003870, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034, 
-0x8ee20034, 0x8003870, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc, 
-0x8ee201dc, 0x8003870, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0, 
-0x8ee201e0, 0x8003870, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4, 
-0x8ee201e4, 0x8003870, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030, 
-0x8ee20030, 0x8003870, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8, 
-0x8ee201e8, 0x42042, 0x1087033c, 0x0, 0x8003835, 0x0, 
+0x0, 0x8003906, 0x42042, 0x10650023, 0xa3102b, 0x14400005, 
+0x0, 0x10690019, 0x0, 0x8003906, 0x42042, 0x10680021, 
+0x0, 0x8003906, 0x42042, 0x8ee20034, 0x24420001, 0xaee20034, 
+0x8ee20034, 0x8003906, 0x42042, 0x8ee201dc, 0x24420001, 0xaee201dc, 
+0x8ee201dc, 0x8003906, 0x42042, 0x8ee201e0, 0x24420001, 0xaee201e0, 
+0x8ee201e0, 0x8003906, 0x42042, 0x8ee201e4, 0x24420001, 0xaee201e4, 
+0x8ee201e4, 0x8003906, 0x42042, 0x8ee20030, 0x24420001, 0xaee20030, 
+0x8ee20030, 0x8003906, 0x42042, 0x8ee201e8, 0x24420001, 0xaee201e8, 
+0x8ee201e8, 0x42042, 0x1087033e, 0x0, 0x80038cb, 0x0, 
 0x3c020001, 0x571021, 0x904283a2, 0x14400084, 0x24020001, 0x3c030001, 
 0x771821, 0x906383a3, 0x1462007f, 0x3c020100, 0x8e430000, 0x621024, 
 0x1040006f, 0x2402ffff, 0x14620005, 0x24110001, 0x96430004, 0x3402ffff, 
@@ -1749,491 +1774,487 @@
 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 0x96020002, 
 0x14620005, 0x971021, 0x94437772, 0x96020004, 0x50620008, 0x24070001, 
 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 0x5440ffee, 
-0x520c0, 0x30e200ff, 0x10400300, 0x0, 0x80038fc, 0x0, 
-0x2402021, 0xc00229d, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 
-0x9442726c, 0x30424000, 0x144002f4, 0xb71021, 0x9443726e, 0x96020000, 
+0x520c0, 0x30e200ff, 0x10400302, 0x0, 0x8003992, 0x0, 
+0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 0x2e51021, 
+0x9442726c, 0x30424000, 0x144002f6, 0xb71021, 0x9443726e, 0x96020000, 
 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96020002, 0x14620006, 
 0x418c0, 0xb71021, 0x94437272, 0x96020004, 0x10620035, 0x418c0, 
-0x2e31021, 0x9442726c, 0x30428000, 0x144002e1, 0x2e31021, 0x944e726c, 
-0x96070000, 0xe28c0, 0xb71021, 0x9442736e, 0x80038de, 0x3021, 
-0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944e736c, 0x30638000, 
-0x14600010, 0xe28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1c02021, 
+0x2e31021, 0x9442726c, 0x30428000, 0x144002e3, 0x2e31021, 0x944d726c, 
+0x96070000, 0xd28c0, 0xb71021, 0x9442736e, 0x8003974, 0x3021, 
+0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944d736c, 0x30638000, 
+0x14600010, 0xd28c0, 0xb71021, 0x9442736e, 0x1447fff5, 0x1a02021, 
 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, 0xb71021, 
 0x94437372, 0x96020004, 0x5462ffec, 0x420c0, 0x24060001, 0x30c200ff, 
-0x104002c0, 0x0, 0x80038fc, 0x0, 0x97430202, 0x96420000, 
-0x146202ba, 0x0, 0x97430204, 0x96420002, 0x146202b6, 0x0, 
-0x97430206, 0x96420004, 0x146202b2, 0x0, 0x92420000, 0x3a230001, 
+0x104002c2, 0x0, 0x8003992, 0x0, 0x97430202, 0x96420000, 
+0x146202bc, 0x0, 0x97430204, 0x96420002, 0x146202b8, 0x0, 
+0x97430206, 0x96420004, 0x146202b4, 0x0, 0x92420000, 0x3a230001, 
 0x30420001, 0x431024, 0x10400074, 0x2402ffff, 0x8e030000, 0x14620004, 
-0x3402ffff, 0x96030004, 0x1062006f, 0x24160002, 0x3c020001, 0x571021, 
-0x904283a2, 0x1440006a, 0x24160003, 0x92e204c8, 0x14400067, 0x0, 
+0x3402ffff, 0x96030004, 0x1062006f, 0x24150002, 0x3c020001, 0x571021, 
+0x904283a2, 0x1440006a, 0x24150003, 0x92e204c8, 0x14400067, 0x0, 
 0x3c020001, 0x571021, 0x8c4283a4, 0x28420005, 0x10400020, 0x3821, 
 0x3c020001, 0x571021, 0x8c4283a4, 0x18400016, 0x2821, 0x96060000, 
 0x520c0, 0x971021, 0x9442776e, 0x14460009, 0x971021, 0x94437770, 
 0x96020002, 0x14620005, 0x971021, 0x94437772, 0x96020004, 0x50620008, 
 0x24070001, 0x3c020001, 0x571021, 0x8c4283a4, 0x24a50001, 0xa2102a, 
-0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24160003, 0x8003bad, 
-0x0, 0x2402021, 0xc00229d, 0x24050006, 0x3044001f, 0x428c0, 
-0x2e51021, 0x9442726c, 0x30424000, 0x1440026f, 0xb71021, 0x9443726e, 
+0x5440ffee, 0x520c0, 0x30e200ff, 0x14400044, 0x24150003, 0x8003c45, 
+0x0, 0x2402021, 0xc0022f8, 0x24050006, 0x3044001f, 0x428c0, 
+0x2e51021, 0x9442726c, 0x30424000, 0x14400271, 0xb71021, 0x9443726e, 
 0x96020000, 0x1462000b, 0x418c0, 0xb71021, 0x94437270, 0x96020002, 
 0x14620006, 0x418c0, 0xb71021, 0x94437272, 0x96020004, 0x10620027, 
-0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x1440025c, 0x2e31021, 
-0x944e726c, 0x96070000, 0xe28c0, 0xb71021, 0x9442736e, 0x8003963, 
-0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944e736c, 
-0x30638000, 0x14600010, 0xe28c0, 0xb71021, 0x9442736e, 0x1447fff5, 
-0x1c02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, 
+0x418c0, 0x2e31021, 0x9442726c, 0x30428000, 0x1440025e, 0x2e31021, 
+0x944d726c, 0x96070000, 0xd28c0, 0xb71021, 0x9442736e, 0x80039f9, 
+0x3021, 0x420c0, 0x2e41021, 0x9443736c, 0x2e41021, 0x944d736c, 
+0x30638000, 0x14600010, 0xd28c0, 0xb71021, 0x9442736e, 0x1447fff5, 
+0x1a02021, 0xb71021, 0x94437370, 0x96020002, 0x5462fff1, 0x420c0, 
 0xb71021, 0x94437372, 0x96020004, 0x5462ffec, 0x420c0, 0x24060001, 
-0x30c200ff, 0x1040023b, 0x0, 0x8003976, 0x24160003, 0x24160001, 
+0x30c200ff, 0x1040023d, 0x0, 0x8003a0c, 0x24150003, 0x24150001, 
 0x8f420260, 0x53102b, 0x10400036, 0x0, 0x8f8300e4, 0x8f8200e0, 
 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8ee400c0, 0x8ee500c4, 
 0x2601821, 0x1021, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 
 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, 0xafa20010, 
-0x8f8200e4, 0x3c040001, 0x24844a20, 0xafa20014, 0x8fa60018, 0x8fa7001c, 
-0x3c050006, 0xc0023a7, 0x34a5f203, 0x8003bb3, 0x0, 0x8ee25230, 
-0xafa20010, 0x8ee25234, 0x3c040001, 0x24844a2c, 0xafa20014, 0x8ee60e00, 
-0x8ee70e08, 0x3c050006, 0xc0023a7, 0x34a5f202, 0x8ee201bc, 0x24420001, 
-0xaee201bc, 0x8003b5a, 0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, 
-0x3c1e8000, 0x126001c9, 0x3c0f001f, 0x35efffff, 0x3c18fff5, 0x37181000, 
-0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x1062019d, 0x0, 
-0x13c00012, 0x0, 0x8ee35230, 0x8ee25234, 0x1062000a, 0x26f95234, 
-0x8ef55234, 0xafb90024, 0x8ee35234, 0x21140, 0x24425238, 0x2e28821, 
-0x24630001, 0x80039de, 0x306e00ff, 0x8ee201d0, 0x24420001, 0xaee201d0, 
-0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffcb, 0x26f90e08, 0x8ef50e08, 
-0xf021, 0xafb90024, 0x8ee30e08, 0x21140, 0x24420e10, 0x2e28821, 
-0x24630001, 0x306e01ff, 0x96e2046a, 0x30420010, 0x10400018, 0x34028100, 
-0x9643000c, 0x14620015, 0x0, 0x3c020001, 0x571021, 0x904283b0, 
-0x14400010, 0x0, 0x9642000e, 0xa6220016, 0x8e420008, 0x8e430004, 
-0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 0x9622000e, 
-0x26100004, 0x24190001, 0xa3b9002f, 0x34420200, 0xa622000e, 0x8e220000, 
-0x8e230004, 0x3c040001, 0x34843800, 0x2003021, 0x306b0007, 0x20b8023, 
-0x3641021, 0x202102b, 0x10400005, 0x26b9821, 0x2041023, 0x3621823, 
-0x3c020020, 0x438023, 0x26620007, 0x9623000a, 0x2419fff8, 0x59a024, 
-0x6b1821, 0x74102b, 0x10400002, 0x2806821, 0x606821, 0x1a01821, 
-0x24620007, 0x2419fff8, 0x596824, 0x26d102b, 0x14400004, 0x1b32823, 
-0x1a32823, 0x8003a1c, 0xc31021, 0xd31021, 0x4b2023, 0x1e4102b, 
-0x54400001, 0x982021, 0x25620040, 0x4d102b, 0x14400035, 0x6021, 
-0x94c3000c, 0x24020800, 0x54620032, 0xae260018, 0x3c020001, 0x571021, 
-0x904283b0, 0x5440002d, 0xae260018, 0x24c20017, 0x1e2102b, 0x10400013, 
-0x0, 0x3c02fff5, 0x461021, 0x90421017, 0x38430006, 0x2c630001, 
-0x38420011, 0x2c420001, 0x621825, 0x10600014, 0x24c20010, 0x1e2102b, 
-0x1040000e, 0x0, 0x3c0cfff5, 0x1866021, 0x958c1010, 0x8003a4d, 
-0x2582000e, 0x90c20017, 0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 
-0x621825, 0x10600005, 0x1801821, 0x94cc0010, 0x2582000e, 0x4b6021, 
-0x1801821, 0x24620007, 0x2419fff8, 0x596024, 0xc31021, 0x4b2023, 
-0x1e4102b, 0x10400002, 0x1832823, 0x982021, 0xae260018, 0x3c020001, 
-0x571021, 0x904283b0, 0x2102b, 0x216c0, 0x15800002, 0xafa20044, 
-0x1a06021, 0x30820001, 0x10400007, 0x4021, 0x90880000, 0x24840001, 
-0x1e4102b, 0x10400002, 0x24a5ffff, 0x982021, 0x50a00012, 0x81c02, 
+0x8f8200e4, 0x3c040001, 0x24844c30, 0xafa20014, 0x8fa60018, 0x8fa7001c, 
+0x3c050006, 0xc002403, 0x34a5f203, 0x8003c4b, 0x0, 0x8ee25230, 
+0xafa20010, 0x8ee25234, 0x3c040001, 0x24844c3c, 0xafa20014, 0x8ee60e00, 
+0x8ee70e08, 0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201bc, 0x24420001, 
+0xaee201bc, 0x8003bf2, 0x8ee201bc, 0x96e20468, 0x53102b, 0x54400001, 
+0x3c168000, 0x126001cb, 0x3c0e001f, 0x35ceffff, 0x3c0ffff5, 0x35ef1000, 
+0x241e0040, 0x8ee2723c, 0x8f430280, 0x24420001, 0x304203ff, 0x1062019e, 
+0x0, 0x12c00012, 0x0, 0x8ee35230, 0x8ee25234, 0x1062000a, 
+0x26f85234, 0x8ef45234, 0xafb80024, 0x8ee35234, 0x21140, 0x24425238, 
+0x2e28821, 0x24630001, 0x8003a75, 0x306d00ff, 0x8ee201d0, 0x24420001, 
+0xaee201d0, 0x8ee201d0, 0x8ee30e00, 0x8ee20e08, 0x1062ffca, 0x26f80e08, 
+0x8ef40e08, 0xb021, 0xafb80024, 0x8ee30e08, 0x21140, 0x24420e10, 
+0x2e28821, 0x24630001, 0x306d01ff, 0x96e2046a, 0x30420010, 0x10400018, 
+0x34028100, 0x9643000c, 0x14620015, 0x0, 0x3c020001, 0x571021, 
+0x904283b0, 0x14400010, 0x0, 0x9642000e, 0xa6220016, 0x8e420008, 
+0x8e430004, 0x8e440000, 0x2673fffc, 0xae42000c, 0xae430008, 0xae440004, 
+0x9622000e, 0x26100004, 0x24180001, 0xa3b8002f, 0x34420200, 0xa622000e, 
+0x8e220000, 0x8e230004, 0x3c040001, 0x34843800, 0x2003021, 0x306a0007, 
+0x20a8023, 0x3641021, 0x202102b, 0x10400005, 0x26a9821, 0x2041023, 
+0x3621823, 0x3c020020, 0x438023, 0x26620007, 0x9623000a, 0x2418fff8, 
+0x58c824, 0x6a1821, 0x79102b, 0x10400002, 0x3206021, 0x606021, 
+0x1801821, 0x24620007, 0x2418fff8, 0x586024, 0x26c102b, 0x14400004, 
+0x1932823, 0x1832823, 0x8003ab3, 0xc31021, 0xd31021, 0x4a2023, 
+0x1c4102b, 0x54400001, 0x8f2021, 0x25420040, 0x4c102b, 0x14400035, 
+0x5821, 0x94c3000c, 0x24020800, 0x54620032, 0xae260018, 0x3c020001, 
+0x571021, 0x904283b0, 0x5440002d, 0xae260018, 0x24c20017, 0x1c2102b, 
+0x10400013, 0x0, 0x3c02fff5, 0x461021, 0x90421017, 0x38430006, 
+0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x10600014, 0x24c20010, 
+0x1c2102b, 0x1040000e, 0x0, 0x3c0bfff5, 0x1665821, 0x956b1010, 
+0x8003ae4, 0x2562000e, 0x90c20017, 0x38430006, 0x2c630001, 0x38420011, 
+0x2c420001, 0x621825, 0x10600005, 0x1601821, 0x94cb0010, 0x2562000e, 
+0x4a5821, 0x1601821, 0x24620007, 0x2418fff8, 0x585824, 0xc31021, 
+0x4a2023, 0x1c4102b, 0x10400002, 0x1632823, 0x8f2021, 0xae260018, 
+0x3c020001, 0x571021, 0x904283b0, 0x2102b, 0x216c0, 0x15600002, 
+0xafa20044, 0x1805821, 0x30820001, 0x10400007, 0x4021, 0x90880000, 
+0x24840001, 0x1c4102b, 0x10400002, 0x24a5ffff, 0x8f2021, 0x50a00012, 
+0x81c02, 0x2ca20002, 0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 
+0x1024021, 0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b11, 0x8f2021, 
+0x90820000, 0x21200, 0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 
+0x3102ffff, 0x624021, 0x3108ffff, 0x1402821, 0x11400011, 0x2002021, 
 0x2ca20002, 0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 0x1024021, 
-0x1e4102b, 0x10400006, 0x24a5fffe, 0x8003a7a, 0x982021, 0x90820000, 
+0x1c4102b, 0x10400006, 0x24a5fffe, 0x8003b28, 0x8f2021, 0x90820000, 
 0x21200, 0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff, 
-0x624021, 0x3108ffff, 0x1602821, 0x11600011, 0x2002021, 0x2ca20002, 
-0x54400009, 0x24a5ffff, 0x94820000, 0x24840002, 0x1024021, 0x1e4102b, 
-0x10400006, 0x24a5fffe, 0x8003a91, 0x982021, 0x90820000, 0x21200, 
-0x1024021, 0x14a0fff2, 0x2ca20002, 0x81c02, 0x3102ffff, 0x624021, 
-0x81c02, 0x3102ffff, 0x8f890120, 0x624021, 0x27623800, 0x252a0020, 
-0x142102b, 0x14400002, 0x3108ffff, 0x276a3000, 0x8f820128, 0x15420007, 
-0x1602821, 0x8ee201a0, 0x3821, 0x24420001, 0xaee201a0, 0x8003b21, 
-0x8ee201a0, 0x8e260000, 0x8e270004, 0x81400, 0x3443000b, 0xad300008, 
-0xa52c000e, 0xad230018, 0x8fb90044, 0x2021, 0x2be1025, 0x591025, 
-0xad22001c, 0xe5102b, 0xe53823, 0xc43023, 0xc23023, 0xad260000, 
-0xad270004, 0x8ee204b0, 0xad220010, 0xaf8a0120, 0x92e24e10, 0x14400061, 
-0x24070001, 0x2462ffee, 0x2c420002, 0x14400003, 0x24020011, 0x14620025, 
-0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
-0x24020012, 0x1462000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 
-0x24190040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x1059002b, 0x0, 0x8003aff, 0x0, 0x8ee24e20, 
-0x24190040, 0x24420001, 0x50590003, 0x1021, 0x8ee24e20, 0x24420001, 
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8003b1e, 
-0x24020012, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
-0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x24190040, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x10590007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8003b0b, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 
-0xac800000, 0x8003b21, 0x0, 0x8ee24e20, 0x24190040, 0x24420001, 
-0x50590003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 
-0xac820004, 0x14e00019, 0x3c050006, 0x3c040001, 0x248449f0, 0x8e220018, 
-0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x1803821, 
-0xc0023a7, 0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100, 0x8e430004, 
-0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000, 0xae440004, 0xae450008, 
-0x96220016, 0x8003b5a, 0xa642000e, 0x15b4000a, 0x26b1823, 0x9622000e, 
-0xa623000a, 0x34420004, 0xa622000e, 0x3c010001, 0x370821, 0xa02083b0, 
-0x8003b57, 0x9821, 0x9624000a, 0x83102b, 0x54400001, 0x801821, 
-0x24020001, 0xa623000a, 0x3c010001, 0x370821, 0xa02283b0, 0x9622000a, 
-0x4b1821, 0x2038021, 0x1f0102b, 0x54400001, 0x2188021, 0x2639823, 
-0xf021, 0x8fb90024, 0x1660fe5f, 0xaf2e0000, 0x12600022, 0x0, 
-0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 0x370821, 0xac3083b8, 
-0x3c010001, 0x370821, 0xac3283bc, 0x93a2002f, 0x10400008, 0x0, 
-0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, 0x3c010001, 0x370821, 
-0xac2283bc, 0x8f430280, 0x8ee2723c, 0x14620006, 0x0, 0x8ee201c0, 
-0x24420001, 0xaee201c0, 0x8003bb3, 0x8ee201c0, 0x8ee201b8, 0x24420001, 
-0xaee201b8, 0x8003bb3, 0x8ee201b8, 0x97a4001e, 0x2484fffc, 0x801821, 
-0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 0xa3302b, 0x822021, 
-0x862021, 0x24020002, 0xaee400c0, 0xaee500c4, 0x12c2000f, 0x2ac20003, 
-0x14400017, 0x24020003, 0x16c20015, 0x0, 0x8ee200d0, 0x8ee300d4, 
-0x24630001, 0x2c640001, 0x441021, 0xaee200d0, 0xaee300d4, 0x8ee200d0, 
-0x8003bad, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 0x24630001, 0x2c640001, 
-0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, 0x8003bad, 0x8ee300dc, 
-0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, 0x441021, 0xaee200c8, 
-0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 0x8f8200e0, 0x10620003, 
-0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0068, 0x8fbe0064, 0x8fb60060, 
-0x8fb5005c, 0x8fb40058, 0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, 
-0x3e00008, 0x27bd0070, 0x27bdffe0, 0xafbf0018, 0x8ee30e04, 0x8ee20dfc, 
-0x10620071, 0x0, 0x8ee30dfc, 0x8ee20e04, 0x622023, 0x4820001, 
-0x24840200, 0x8ee30e08, 0x8ee20e04, 0x43102b, 0x14400004, 0x24020200, 
-0x8ee30e04, 0x8003bd5, 0x431823, 0x8ee20e08, 0x8ee30e04, 0x431023, 
+0x624021, 0x81c02, 0x3102ffff, 0x8f890120, 0x624021, 0x27623800, 
+0x25230020, 0x62102b, 0x14400002, 0x3108ffff, 0x27633000, 0x8f820128, 
+0x10620004, 0x0, 0x8f820124, 0x14620007, 0x1402821, 0x8ee201a0, 
+0x3821, 0x24420001, 0xaee201a0, 0x8003bb9, 0x8ee201a0, 0x8e260000, 
+0x8e270004, 0x81400, 0x3448000b, 0xad300008, 0xa52b000e, 0xad280018, 
+0x8fb80044, 0x2021, 0x2961025, 0x581025, 0xad22001c, 0xe5102b, 
+0xe53823, 0xc43023, 0xc23023, 0xad260000, 0xad270004, 0x8ee204b0, 
+0xad220010, 0xaf830120, 0x92e24e10, 0x1440005f, 0x24070001, 0x2502ffee, 
+0x2c420002, 0x14400003, 0x24020011, 0x15020024, 0x0, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020012, 0x1462000f, 
+0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 0x0, 0x8c820004, 
+0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x105e002a, 
+0x0, 0x8003b98, 0x0, 0x8ee24e20, 0x24420001, 0x505e0003, 
+0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0x8003bb6, 0x24020012, 0x8ee24e20, 0x210c0, 
+0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 
+0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 
+0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x105e0007, 0x0, 
+0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x8003ba4, 0x0, 
+0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
+0x8c820004, 0x2c420011, 0x50400012, 0xac800000, 0x8003bb9, 0x0, 
+0x8ee24e20, 0x24420001, 0x505e0003, 0x1021, 0x8ee24e20, 0x24420001, 
+0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020007, 
+0xac820000, 0x24020001, 0xac820004, 0x14e00019, 0x3c050006, 0x3c040001, 
+0x24844c00, 0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, 
+0x2203021, 0x1603821, 0xc002403, 0xafa30014, 0x93a2002f, 0x1040002a, 
+0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c, 0xa642000c, 0xae430000, 
+0xae440004, 0xae450008, 0x96220016, 0x8003bf2, 0xa642000e, 0x1599000a, 
+0x26a1823, 0x9622000e, 0xa623000a, 0x34420004, 0xa622000e, 0x3c010001, 
+0x370821, 0xa02083b0, 0x8003bef, 0x9821, 0x9624000a, 0x83102b, 
+0x54400001, 0x801821, 0x24020001, 0xa623000a, 0x3c010001, 0x370821, 
+0xa02283b0, 0x9622000a, 0x4a1821, 0x2038021, 0x1d0102b, 0x54400001, 
+0x20f8021, 0x2639823, 0xb021, 0x8fb80024, 0x1660fe5e, 0xaf0d0000, 
+0x12600022, 0x0, 0x3c010001, 0x370821, 0xac3383b4, 0x3c010001, 
+0x370821, 0xac3083b8, 0x3c010001, 0x370821, 0xac3283bc, 0x93a2002f, 
+0x10400008, 0x0, 0x3c020001, 0x571021, 0x8c4283bc, 0x24420004, 
+0x3c010001, 0x370821, 0xac2283bc, 0x8f430280, 0x8ee2723c, 0x14620006, 
+0x0, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003c4b, 0x8ee201c0, 
+0x8ee201b8, 0x24420001, 0xaee201b8, 0x8003c4b, 0x8ee201b8, 0x97a4001e, 
+0x2484fffc, 0x801821, 0x8ee400c0, 0x8ee500c4, 0x1021, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0x24020002, 0xaee400c0, 0xaee500c4, 
+0x12a2000f, 0x2aa20003, 0x14400017, 0x24020003, 0x16a20015, 0x0, 
+0x8ee200d0, 0x8ee300d4, 0x24630001, 0x2c640001, 0x441021, 0xaee200d0, 
+0xaee300d4, 0x8ee200d0, 0x8003c45, 0x8ee300d4, 0x8ee200d8, 0x8ee300dc, 
+0x24630001, 0x2c640001, 0x441021, 0xaee200d8, 0xaee300dc, 0x8ee200d8, 
+0x8003c45, 0x8ee300dc, 0x8ee200c8, 0x8ee300cc, 0x24630001, 0x2c640001, 
+0x441021, 0xaee200c8, 0xaee300cc, 0x8ee200c8, 0x8ee300cc, 0x8f8300e4, 
+0x8f8200e0, 0x10620003, 0x24630008, 0xaf8300e4, 0xaf8300e8, 0x8fbf0068, 
+0x8fbe0064, 0x8fb60060, 0x8fb5005c, 0x8fb40058, 0x8fb30054, 0x8fb20050, 
+0x8fb1004c, 0x8fb00048, 0x3e00008, 0x27bd0070, 0x27bdffe0, 0xafbf0018, 
+0x8ee30e04, 0x8ee20dfc, 0x10620074, 0x0, 0x8ee30dfc, 0x8ee20e04, 
+0x622023, 0x4820001, 0x24840200, 0x8ee30e08, 0x8ee20e04, 0x43102b, 
+0x14400004, 0x24020200, 0x8ee30e04, 0x8003c6d, 0x431823, 0x8ee20e08, 
+0x8ee30e04, 0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001, 
+0x604821, 0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001, 
+0x27682800, 0x8f820108, 0x11020004, 0x0, 0x8f820104, 0x15020007, 
+0x1021, 0x8ee201a4, 0x2021, 0x24420001, 0xaee201a4, 0x8003caf, 
+0x8ee201a4, 0x8ee40e04, 0x42140, 0x801821, 0x8ee40460, 0x8ee50464, 
+0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 
+0x8ee30e04, 0x91140, 0xa4e2000e, 0x24020002, 0xace20018, 0x31940, 
+0x24630e10, 0x2e31021, 0xace20008, 0x8ee20e04, 0xace2001c, 0x8ee204bc, 
+0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 0x24040001, 0x8ee24e18, 
+0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 
+0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 0x24020002, 
+0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee20e04, 
+0xafa20010, 0x8ee20e08, 0x3c050007, 0xafa20014, 0x8ee60dfc, 0x8ee70e00, 
+0x3c040001, 0x24844c44, 0xc002403, 0x34a5f001, 0x8003ccd, 0x0, 
+0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 0x8ee204f0, 0x24420001, 
+0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 0xac4904f8, 0x8ee20e04, 
+0x491021, 0x304201ff, 0xaee20e04, 0x8ee30e04, 0x8ee20dfc, 0x14620005, 
+0x0, 0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8ee3522c, 0x8ee25228, 
+0x10620074, 0x0, 0x8ee35228, 0x8ee2522c, 0x622023, 0x4820001, 
+0x24840100, 0x8ee35234, 0x8ee2522c, 0x43102b, 0x14400004, 0x24020100, 
+0x8ee3522c, 0x8003cef, 0x431823, 0x8ee25234, 0x8ee3522c, 0x431023, 
 0x2443ffff, 0x804821, 0x69102a, 0x54400001, 0x604821, 0x8f870100, 
 0x27623000, 0x24e80020, 0x102102b, 0x50400001, 0x27682800, 0x8f820108, 
-0x15020007, 0x1021, 0x8ee201a4, 0x2021, 0x24420001, 0xaee201a4, 
-0x8003c14, 0x8ee201a4, 0x8ee40e04, 0x42140, 0x801821, 0x8ee40460, 
-0x8ee50464, 0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 
-0xace50004, 0x8ee30e04, 0x91140, 0xa4e2000e, 0x24020002, 0xace20018, 
-0x31940, 0x24630e10, 0x2e31021, 0xace20008, 0x8ee20e04, 0xace2001c, 
-0x8ee204bc, 0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 0x24040001, 
-0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e18, 
-0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 0x2e21821, 
-0x24020002, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 
-0x8ee20e04, 0xafa20010, 0x8ee20e08, 0x3c050007, 0xafa20014, 0x8ee60dfc, 
-0x8ee70e00, 0x3c040001, 0x24844a34, 0xc0023a7, 0x34a5f001, 0x8003c32, 
-0x0, 0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 0x8ee204f0, 
-0x24420001, 0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 0xac4904f8, 
-0x8ee20e04, 0x491021, 0x304201ff, 0xaee20e04, 0x8ee30e04, 0x8ee20dfc, 
-0x14620005, 0x0, 0x8f820060, 0x2403fdff, 0x431024, 0xaf820060, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8ee3522c, 
-0x8ee25228, 0x10620071, 0x0, 0x8ee35228, 0x8ee2522c, 0x622023, 
-0x4820001, 0x24840100, 0x8ee35234, 0x8ee2522c, 0x43102b, 0x14400004, 
-0x24020100, 0x8ee3522c, 0x8003c54, 0x431823, 0x8ee25234, 0x8ee3522c, 
-0x431023, 0x2443ffff, 0x804821, 0x69102a, 0x54400001, 0x604821, 
-0x8f870100, 0x27623000, 0x24e80020, 0x102102b, 0x50400001, 0x27682800, 
-0x8f820108, 0x15020007, 0x1021, 0x8ee201a4, 0x2021, 0x24420001, 
-0xaee201a4, 0x8003c93, 0x8ee201a4, 0x8ee4522c, 0x42140, 0x801821, 
-0x8ee40470, 0x8ee50474, 0xa32821, 0xa3302b, 0x822021, 0x862021, 
-0xace40000, 0xace50004, 0x8ee3522c, 0x91140, 0xa4e2000e, 0x24020003, 
-0xace20018, 0x31940, 0x24635238, 0x2e31021, 0xace20008, 0x8ee2522c, 
-0xace2001c, 0x8ee204bc, 0xace20010, 0xaf880100, 0x92e204dc, 0x14400011, 
-0x24040001, 0x8ee24e18, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 0x210c0, 0x24424e28, 
-0x2e21821, 0x24020003, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, 
-0x24030040, 0x8ee2522c, 0xafa20010, 0x8ee25234, 0x3c050007, 0xafa20014, 
-0x8ee65228, 0x8ee75230, 0x3c040001, 0x24844a40, 0xc0023a7, 0x34a5f010, 
-0x8003cb1, 0x0, 0x8ee204f0, 0x24420001, 0x50430003, 0x1021, 
-0x8ee204f0, 0x24420001, 0xaee204f0, 0x8ee204f0, 0x21080, 0x571021, 
-0xac4904f8, 0x8ee2522c, 0x491021, 0x304200ff, 0xaee2522c, 0x8ee3522c, 
-0x8ee25228, 0x14620005, 0x0, 0x8f820060, 0x2403feff, 0x431024, 
-0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f820120, 0x8ee34e24, 
-0x8f820124, 0x8f860128, 0x24020040, 0x24630001, 0x50620003, 0x1021, 
-0x8ee24e24, 0x24420001, 0xaee24e24, 0x8ee24e24, 0x8ee44e24, 0x8ee34e20, 
-0x210c0, 0x24425028, 0x14830007, 0x2e22821, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x8003ce4, 0xaca00000, 0x8ee24e24, 0x24030040, 
-0x24420001, 0x50430003, 0x1021, 0x8ee24e24, 0x24420001, 0x210c0, 
-0x24425028, 0x2e22821, 0x8ca20004, 0x8f830128, 0x21140, 0x621821, 
-0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012, 0x10400008, 
-0x31080, 0x3c010001, 0x220821, 0x8c224a50, 0x400008, 0x0, 
-0x24020001, 0xaee24e14, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0030, 
-0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 
-0x8f830128, 0x8f820124, 0x106202a7, 0xa021, 0x3c11001f, 0x3631ffff, 
-0x3c12fff5, 0x36521000, 0x24150012, 0x24130040, 0x8f8c0128, 0x8f820128, 
-0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe, 0x2c620012, 
-0x10400293, 0x31080, 0x3c010001, 0x220821, 0x8c224aa8, 0x400008, 
-0x0, 0x8f420218, 0x30420100, 0x10400007, 0x0, 0x95830016, 
-0x95820018, 0x621823, 0x31402, 0x431021, 0xa5820016, 0x8d82001c, 
-0x3c038000, 0x3044ffff, 0x436824, 0x3c030800, 0x431824, 0x11a00004, 
-0xad84001c, 0x41140, 0x8003d2a, 0x24425238, 0x41140, 0x24420e10, 
-0x2e25821, 0x9562000e, 0x3042fffc, 0x10600004, 0xa562000e, 0x95840016, 
-0x8003e12, 0x0, 0x8d690018, 0x4021, 0x952a0000, 0x25290002, 
-0x95270000, 0x25290002, 0x95260000, 0x25290002, 0x95250000, 0x25290002, 
-0x95240000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002, 
-0x1475021, 0x1465021, 0x1455021, 0x1445021, 0x1435021, 0x1425021, 
-0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, 0x625021, 
-0x96e2046a, 0x314effff, 0x30420002, 0x10400044, 0x5021, 0x25220014, 
-0x222102b, 0x10400014, 0x1201821, 0x2405000a, 0x2021, 0x223102b, 
-0x54400001, 0x721821, 0x94620000, 0x24630002, 0x24a5ffff, 0x14a0fff9, 
-0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x41402, 0x3083ffff, 
-0x431021, 0x3042ffff, 0x8003d85, 0x1425021, 0x952a0000, 0x25290002, 
-0x95280000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002, 
-0x95250000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002, 
-0x95240000, 0x25290002, 0x1485021, 0x1475021, 0x1465021, 0x1455021, 
-0x1435021, 0x1425021, 0x95220000, 0x95230002, 0x1445021, 0x1425021, 
-0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, 
-0x625021, 0x3148ffff, 0x51000001, 0x3408ffff, 0x8d620018, 0x9443000c, 
-0x24020800, 0x54620005, 0xa5680010, 0x9562000e, 0x34420002, 0xa562000e, 
-0xa5680010, 0x96e2046a, 0x2821, 0x30420008, 0x14400056, 0x3021, 
-0x8d630018, 0x24620024, 0x222102b, 0x10400034, 0x24690010, 0x229102b, 
-0x54400001, 0x1324821, 0x95250000, 0x24690014, 0x229102b, 0x10400002, 
-0x24a5ffec, 0x1324821, 0x95220000, 0x30420fff, 0x14400003, 0x25290002, 
-0x8003db2, 0x24140001, 0xa021, 0xa03021, 0x229102b, 0x54400001, 
-0x1324821, 0x91220001, 0x25290002, 0xa22821, 0x229102b, 0x54400001, 
-0x1324821, 0x25290002, 0x229102b, 0x54400001, 0x1324821, 0x95220000, 
-0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000, 
-0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000, 
-0x25290002, 0xa22821, 0x229102b, 0x54400001, 0x1324821, 0x95220000, 
-0x8003deb, 0xa22821, 0x94650010, 0x94620014, 0x24690016, 0x30420fff, 
-0x14400003, 0x24a5ffec, 0x8003dde, 0x24140001, 0xa021, 0xa03021, 
-0x91230001, 0x25290004, 0x95220000, 0x25290002, 0x95240000, 0x25290002, 
-0xa32821, 0xa22821, 0x95220000, 0x95230002, 0xa42821, 0xa22821, 
-0xa32821, 0x51c02, 0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff, 
-0x622821, 0x96e2046a, 0x30420001, 0x1040001e, 0x2021, 0x95820016, 
-0x4e2023, 0x41402, 0x822021, 0x328200ff, 0x50400002, 0x862021, 
-0x852021, 0x41402, 0x822021, 0x3084ffff, 0x50800001, 0x3404ffff, 
-0x8d620018, 0x24430017, 0x223102b, 0x54400001, 0x721821, 0x90620000, 
-0x38430011, 0x2c630001, 0x38420006, 0x2c420001, 0x621825, 0x10600004, 
-0x0, 0x9562000e, 0x34420001, 0xa562000e, 0x9562000e, 0x240a0002, 
-0x30420004, 0x10400002, 0xa5640012, 0x240a0004, 0x8f880120, 0x27623800, 
-0x25090020, 0x122102b, 0x50400001, 0x27693000, 0x8f820128, 0x15220007, 
-0x24040020, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003e9e, 
-0x8ee201a0, 0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xad0b0008, 0xa504000e, 
-0xad0a0018, 0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 
-0xc23021, 0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0x4d1025, 
-0xad02001c, 0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400060, 
-0x24100001, 0x2543ffee, 0x2c630002, 0x39420011, 0x2c420001, 0x621825, 
-0x10600024, 0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0x8c820000, 0x1455000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x1053002b, 0x0, 0x8003e7d, 0x0, 0x8ee24e20, 
-0x24420001, 0x50530003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 
-0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0x8003e9d, 
-0xac950000, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 
-0x24020007, 0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8003e89, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400012, 
-0xac800000, 0x8003e9e, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 
-0x1600000d, 0x0, 0x8f820120, 0x3c040001, 0x24844a98, 0xafa00014, 
-0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008, 0xc0023a7, 0x34a50001, 
-0x8003fa0, 0x0, 0x8ee2723c, 0x24420001, 0x304203ff, 0x11a00006, 
-0xaee2723c, 0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003eba, 0x8ee201c8, 
-0x8ee201c4, 0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8ee201cc, 0x2442ffff, 
-0xaee201cc, 0x8003fa0, 0x8ee201cc, 0x8f420240, 0x104000df, 0x0, 
-0x8ee20e0c, 0x24420001, 0x8003fa0, 0xaee20e0c, 0x9582001e, 0xad82001c, 
-0x8f420240, 0x1040006f, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 
-0x8f430240, 0x43102b, 0x144000cf, 0x0, 0x8f830120, 0x27623800, 
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 
-0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003f26, 
+0x11020004, 0x0, 0x8f820104, 0x15020007, 0x1021, 0x8ee201a4, 
+0x2021, 0x24420001, 0xaee201a4, 0x8003d31, 0x8ee201a4, 0x8ee4522c, 
+0x42140, 0x801821, 0x8ee40470, 0x8ee50474, 0xa32821, 0xa3302b, 
+0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee3522c, 0x91140, 
+0xa4e2000e, 0x24020003, 0xace20018, 0x31940, 0x24635238, 0x2e31021, 
+0xace20008, 0x8ee2522c, 0xace2001c, 0x8ee204bc, 0xace20010, 0xaf880100, 
+0x92e204dc, 0x14400011, 0x24040001, 0x8ee24e18, 0x24030040, 0x24420001, 
+0x50430003, 0x1021, 0x8ee24e18, 0x24420001, 0xaee24e18, 0x8ee24e18, 
+0x210c0, 0x24424e28, 0x2e21821, 0x24020003, 0xac620000, 0x24020001, 
+0xac620004, 0x1480000e, 0x24030040, 0x8ee2522c, 0xafa20010, 0x8ee25234, 
+0x3c050007, 0xafa20014, 0x8ee65228, 0x8ee75230, 0x3c040001, 0x24844c50, 
+0xc002403, 0x34a5f010, 0x8003d4f, 0x0, 0x8ee204f0, 0x24420001, 
+0x50430003, 0x1021, 0x8ee204f0, 0x24420001, 0xaee204f0, 0x8ee204f0, 
+0x21080, 0x571021, 0xac4904f8, 0x8ee2522c, 0x491021, 0x304200ff, 
+0xaee2522c, 0x8ee3522c, 0x8ee25228, 0x14620005, 0x0, 0x8f820060, 
+0x2403feff, 0x431024, 0xaf820060, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
+0x8f820120, 0x8ee34e24, 0x8f820124, 0x8f860128, 0x24020040, 0x24630001, 
+0x50620003, 0x1021, 0x8ee24e24, 0x24420001, 0xaee24e24, 0x8ee24e24, 
+0x8ee44e24, 0x8ee34e20, 0x210c0, 0x24425028, 0x14830007, 0x2e22821, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8003d82, 0xaca00000, 
+0x8ee24e24, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ee24e24, 
+0x24420001, 0x210c0, 0x24425028, 0x2e22821, 0x8ca20004, 0x8f830128, 
+0x21140, 0x621821, 0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, 
+0x2c620012, 0x10400008, 0x31080, 0x3c010001, 0x220821, 0x8c224c60, 
+0x400008, 0x0, 0x24020001, 0xaee24e14, 0x3e00008, 0x0, 
+0x27bdffc8, 0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, 
+0xafb1001c, 0xafb00018, 0x8f830128, 0x8f820124, 0x106202b0, 0x9821, 
+0x3c11001f, 0x3631ffff, 0x3c12fff5, 0x36521000, 0x24150012, 0x24140040, 
+0x8f8c0128, 0x8f820128, 0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, 
+0x2443fffe, 0x2c620012, 0x1040029c, 0x31080, 0x3c010001, 0x220821, 
+0x8c224cb8, 0x400008, 0x0, 0x8f420218, 0x30420100, 0x10400007, 
+0x0, 0x95830016, 0x95820018, 0x621823, 0x31402, 0x431021, 
+0xa5820016, 0x8d82001c, 0x3c038000, 0x3044ffff, 0x436824, 0x3c030800, 
+0x431824, 0x11a00004, 0xad84001c, 0x41140, 0x8003dc8, 0x24425238, 
+0x41140, 0x24420e10, 0x2e25821, 0x9562000e, 0x3042fffc, 0x10600004, 
+0xa562000e, 0x95840016, 0x8003eb0, 0x0, 0x8d690018, 0x4021, 
+0x952a0000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002, 
+0x95250000, 0x25290002, 0x95240000, 0x25290002, 0x95230000, 0x25290002, 
+0x95220000, 0x25290002, 0x1475021, 0x1465021, 0x1455021, 0x1445021, 
+0x1435021, 0x1425021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 
+0x3142ffff, 0x625021, 0x96e2046a, 0x314effff, 0x30420002, 0x10400044, 
+0x5021, 0x25220014, 0x222102b, 0x10400014, 0x1201821, 0x2405000a, 
+0x2021, 0x223102b, 0x54400001, 0x721821, 0x94620000, 0x24630002, 
+0x24a5ffff, 0x14a0fff9, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 
+0x41402, 0x3083ffff, 0x431021, 0x3042ffff, 0x8003e23, 0x1425021, 
+0x952a0000, 0x25290002, 0x95280000, 0x25290002, 0x95270000, 0x25290002, 
+0x95260000, 0x25290002, 0x95250000, 0x25290002, 0x95230000, 0x25290002, 
+0x95220000, 0x25290002, 0x95240000, 0x25290002, 0x1485021, 0x1475021, 
+0x1465021, 0x1455021, 0x1435021, 0x1425021, 0x95220000, 0x95230002, 
+0x1445021, 0x1425021, 0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 
+0xa1c02, 0x3142ffff, 0x625021, 0x3148ffff, 0x51000001, 0x3408ffff, 
+0x8d620018, 0x9443000c, 0x24020800, 0x54620005, 0xa5680010, 0x9562000e, 
+0x34420002, 0xa562000e, 0xa5680010, 0x96e2046a, 0x2821, 0x30420008, 
+0x14400056, 0x3021, 0x8d630018, 0x24620024, 0x222102b, 0x10400034, 
+0x24690010, 0x229102b, 0x54400001, 0x1324821, 0x95250000, 0x24690014, 
+0x229102b, 0x10400002, 0x24a5ffec, 0x1324821, 0x95220000, 0x30420fff, 
+0x14400003, 0x25290002, 0x8003e50, 0x24130001, 0x9821, 0xa03021, 
+0x229102b, 0x54400001, 0x1324821, 0x91220001, 0x25290002, 0xa22821, 
+0x229102b, 0x54400001, 0x1324821, 0x25290002, 0x229102b, 0x54400001, 
+0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001, 
+0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001, 
+0x1324821, 0x95220000, 0x25290002, 0xa22821, 0x229102b, 0x54400001, 
+0x1324821, 0x95220000, 0x8003e89, 0xa22821, 0x94650010, 0x94620014, 
+0x24690016, 0x30420fff, 0x14400003, 0x24a5ffec, 0x8003e7c, 0x24130001, 
+0x9821, 0xa03021, 0x91230001, 0x25290004, 0x95220000, 0x25290002, 
+0x95240000, 0x25290002, 0xa32821, 0xa22821, 0x95220000, 0x95230002, 
+0xa42821, 0xa22821, 0xa32821, 0x51c02, 0x30a2ffff, 0x622821, 
+0x51c02, 0x30a2ffff, 0x622821, 0x96e2046a, 0x30420001, 0x1040001e, 
+0x2021, 0x95820016, 0x4e2023, 0x41402, 0x822021, 0x326200ff, 
+0x50400002, 0x862021, 0x852021, 0x41402, 0x822021, 0x3084ffff, 
+0x50800001, 0x3404ffff, 0x8d620018, 0x24430017, 0x223102b, 0x54400001, 
+0x721821, 0x90620000, 0x38430011, 0x2c630001, 0x38420006, 0x2c420001, 
+0x621825, 0x10600004, 0x0, 0x9562000e, 0x34420001, 0xa562000e, 
+0x9562000e, 0x240a0002, 0x30420004, 0x10400002, 0xa5640012, 0x240a0004, 
+0x8f880120, 0x27623800, 0x25090020, 0x122102b, 0x50400001, 0x27693000, 
+0x8f820128, 0x11220004, 0x0, 0x8f820124, 0x15220007, 0x24040020, 
+0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8003f3f, 0x8ee201a0, 
+0x8ee5723c, 0x8ee60480, 0x8ee70484, 0xad0b0008, 0xa504000e, 0xad0a0018, 
+0x52940, 0xa01821, 0x1021, 0xe33821, 0xe3202b, 0xc23021, 
+0xc43021, 0xad060000, 0xad070004, 0x8ee2723c, 0x4d1025, 0xad02001c, 
+0x8ee204b4, 0xad020010, 0xaf890120, 0x92e24e10, 0x14400060, 0x24100001, 
+0x2543ffee, 0x2c630002, 0x39420011, 0x2c420001, 0x621825, 0x10600024, 
+0x0, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
+0x1455000f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062000b, 0x0, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
+0x1054002b, 0x0, 0x8003f1e, 0x0, 0x8ee24e20, 0x24420001, 
+0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0x8003f3e, 0xac950000, 
+0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c830000, 0x24020007, 
+0x1462001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
+0x10540007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
+0x8003f2a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400012, 0xac800000, 
+0x8003f3f, 0x0, 0x8ee24e20, 0x24420001, 0x50540003, 0x1021, 
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x1600000d, 
+0x0, 0x8f820120, 0x3c040001, 0x24844ca8, 0xafa00014, 0xafa20010, 
+0x8d86001c, 0x8f870124, 0x3c050008, 0xc002403, 0x34a50001, 0x8004047, 
+0x0, 0x8ee2723c, 0x24420001, 0x304203ff, 0x11a00006, 0xaee2723c, 
+0x8ee201c8, 0x2442ffff, 0xaee201c8, 0x8003f5b, 0x8ee201c8, 0x8ee201c4, 
+0x2442ffff, 0xaee201c4, 0x8ee201c4, 0x8ee201cc, 0x2442ffff, 0xaee201cc, 
+0x8004047, 0x8ee201cc, 0x8f420240, 0x104000e5, 0x0, 0x8ee20e0c, 
+0x24420001, 0x8004047, 0xaee20e0c, 0x9582001e, 0xad82001c, 0x8f420240, 
+0x10400072, 0x0, 0x8ee20e0c, 0x24420001, 0xaee20e0c, 0x8f430240, 
+0x43102b, 0x144000d5, 0x0, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 
+0xaee201a0, 0x8003fca, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 
+0x8ee5049c, 0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 
+0xac620018, 0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 
+0x92e24e10, 0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 
+0x1062001b, 0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 
+0x8ee34e20, 0x24420001, 0x10540007, 0x0, 0x8ee24e24, 0x24420001, 
+0x10620005, 0x0, 0x8003fb6, 0x0, 0x14600005, 0x0, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 
+0x50400011, 0xac800000, 0x8003fca, 0x0, 0x8ee24e20, 0x24420001, 
+0x50540003, 0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 
+0x210c0, 0x24425028, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 
+0x5600000b, 0x24100001, 0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 
+0xafa20010, 0x8ee6723c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 
+0x56000001, 0xaee00e0c, 0x8ee20184, 0x24420001, 0xaee20184, 0x8004040, 
+0x8ee20184, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 
+0x27663000, 0x8f820128, 0x10c20004, 0x0, 0x8f820124, 0x14c20007, 
+0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 0x8004034, 
 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 0x2462001c, 
 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 0xac640000, 
 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400034, 
 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
-0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
-0x8003f12, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0x10540007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
+0x8004020, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400011, 0xac800000, 
-0x8003f26, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, 0x1021, 
+0x8004034, 0x0, 0x8ee24e20, 0x24420001, 0x50540003, 0x1021, 
 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
-0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x5600000b, 0x24100001, 
-0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 0x8ee6723c, 
-0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 0x56000001, 0xaee00e0c, 
-0x8ee20184, 0x24420001, 0xaee20184, 0x8003f99, 0x8ee20184, 0x8f830120, 
-0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 
-0x14c20007, 0x0, 0x8ee201a0, 0x8021, 0x24420001, 0xaee201a0, 
-0x8003f8d, 0x8ee201a0, 0x8ee2723c, 0xac62001c, 0x8ee40498, 0x8ee5049c, 
-0x2462001c, 0xac620008, 0x24020008, 0xa462000e, 0x24020011, 0xac620018, 
-0xac640000, 0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 
-0x14400034, 0x24100001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0x8c820000, 0x1455001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x10530007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8003f79, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400011, 
-0xac800000, 0x8003f8d, 0x0, 0x8ee24e20, 0x24420001, 0x50530003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, 
-0x0, 0x8ee2723c, 0x3c040001, 0x24844a08, 0xafa00014, 0xafa20010, 
-0x8ee6723c, 0x8f470280, 0x3c050009, 0xc0023a7, 0x34a5f008, 0x8ee20170, 
-0x24420001, 0xaee20170, 0x8003fa0, 0x8ee20170, 0x24020001, 0xaee24e14, 
-0x8f830128, 0x8f820124, 0x1462fd61, 0x0, 0x8fbf0030, 0x8fb5002c, 
-0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 
-0x27bd0038, 0x0, 0x0, 0x0, 0x27bdffe8, 0x27840208, 
-0x27450200, 0x24060008, 0xafbf0014, 0xc00243e, 0xafb00010, 0x24040001, 
-0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204, 0xaf820214, 
-0x8f460248, 0x24030004, 0x3c020040, 0x3c010001, 0xac234de8, 0x3c010001, 
-0xac234dec, 0x3c010001, 0xac204e8c, 0x3c010001, 0xac224de4, 0x3c010001, 
-0xac234dec, 0xc004e2c, 0x24050004, 0xc0046b4, 0x0, 0x8ee20000, 
-0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00, 0xaf82021c, 
-0x3c010001, 0x370821, 0xac30839c, 0x8fbf0014, 0x8fb00010, 0x3e00008, 
-0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 
-0xafa00014, 0x8f860200, 0x3c040001, 0x24844b50, 0xc0023a7, 0x3821, 
-0x8ee20270, 0x24420001, 0xaee20270, 0x8ee20270, 0x8f830200, 0x3c023f00, 
-0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 
-0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f900220, 0x8ee20204, 0x3821, 
-0x24420001, 0xaee20204, 0x8ee20204, 0x3c020300, 0x2021024, 0x10400027, 
-0x3c110400, 0xc0041e7, 0x0, 0x3c020100, 0x2021024, 0x10400007, 
-0x0, 0x8ee20208, 0x24420001, 0xaee20208, 0x8ee20208, 0x8004012, 
-0x3c03fdff, 0x8ee2020c, 0x24420001, 0xaee2020c, 0x8ee2020c, 0x3c03fdff, 
-0x3463ffff, 0x3c0808ff, 0x3508ffff, 0x8ee20000, 0x3c040001, 0x24844b5c, 
-0x3c050008, 0x2003021, 0x431024, 0xaee20000, 0x8f820220, 0x3821, 
-0x3c030300, 0x481024, 0x431025, 0xaf820220, 0xafa00010, 0xc0023a7, 
-0xafa00014, 0x80041e2, 0x0, 0x2111024, 0x1040001f, 0x3c024000, 
-0x8f830224, 0x24021402, 0x1462000b, 0x3c03fdff, 0x3c040001, 0x24844b68, 
-0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc0023a7, 
-0x3821, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x2002021, 0x431024, 
-0xc004b88, 0xaee20000, 0x8ee20210, 0x24420001, 0xaee20210, 0x8ee20210, 
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x80041e1, 0x511025, 
-0x2021024, 0x10400142, 0x0, 0x8ee2021c, 0x24420001, 0xaee2021c, 
-0x8ee2021c, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, 
-0xaf820220, 0x8f830054, 0x8f820054, 0x800405a, 0x24630002, 0x8f820054, 
-0x621023, 0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x8f8400e4, 
+0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, 0x0, 
+0x8ee2723c, 0x3c040001, 0x24844c18, 0xafa00014, 0xafa20010, 0x8ee6723c, 
+0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20170, 0x24420001, 
+0xaee20170, 0x8004047, 0x8ee20170, 0x24020001, 0xaee24e14, 0x8f830128, 
+0x8f820124, 0x1462fd58, 0x0, 0x8fbf0030, 0x8fb5002c, 0x8fb40028, 
+0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, 
+0x27bdffe8, 0x27840208, 0x27450200, 0x24060008, 0xafbf0014, 0xc00249a, 
+0xafb00010, 0x24040001, 0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, 
+0xaf800204, 0xaf820214, 0x8f460248, 0x24030004, 0x3c020040, 0x3c010001, 
+0xac234ff8, 0x3c010001, 0xac234ffc, 0x3c010001, 0xac20509c, 0x3c010001, 
+0xac224ff4, 0x3c010001, 0xac234ffc, 0xc004eac, 0x24050004, 0xc004734, 
+0x0, 0x8ee20000, 0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, 
+0x3c023c00, 0xaf82021c, 0x3c010001, 0x370821, 0xac30839c, 0x8fbf0014, 
+0x8fb00010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 
+0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001, 0x24844d60, 
+0xc002403, 0x3821, 0x8ee20270, 0x24420001, 0xaee20270, 0x8ee20270, 
+0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 
+0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f900220, 
+0x8ee20204, 0x3821, 0x24420001, 0xaee20204, 0x8ee20204, 0x3c020300, 
+0x2021024, 0x10400027, 0x3c110400, 0xc00428b, 0x0, 0x3c020100, 
+0x2021024, 0x10400007, 0x0, 0x8ee20208, 0x24420001, 0xaee20208, 
+0x8ee20208, 0x80040b6, 0x3c03fdff, 0x8ee2020c, 0x24420001, 0xaee2020c, 
+0x8ee2020c, 0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff, 0x8ee20000, 
+0x3c040001, 0x24844d6c, 0x3c050008, 0x2003021, 0x431024, 0xaee20000, 
+0x8f820220, 0x3821, 0x3c030300, 0x481024, 0x431025, 0xaf820220, 
+0xafa00010, 0xc002403, 0xafa00014, 0x8004286, 0x0, 0x2111024, 
+0x1040001f, 0x3c024000, 0x8f830224, 0x24021402, 0x1462000b, 0x3c03fdff, 
+0x3c040001, 0x24844d78, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, 
+0x34a5ffff, 0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 
+0x2002021, 0x431024, 0xc004c08, 0xaee20000, 0x8ee20210, 0x24420001, 
+0xaee20210, 0x8ee20210, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 
+0x8004285, 0x511025, 0x2021024, 0x10400142, 0x0, 0x8ee2021c, 
+0x24420001, 0xaee2021c, 0x8ee2021c, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
+0x431024, 0x34420004, 0xaf820220, 0x8f830054, 0x8f820054, 0x80040fe, 
+0x24630002, 0x8f820054, 0x621023, 0x2c420003, 0x1440fffc, 0x0, 
+0x8f8600e0, 0x8f8400e4, 0x30c20007, 0x10400012, 0x0, 0x8f8300e4, 
+0x2402fff8, 0xc21024, 0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 
+0x14c30009, 0x24440050, 0x8f820054, 0x821023, 0x2c420051, 0x10400004, 
+0x0, 0x8f8200e0, 0x10c2fff9, 0x0, 0x8f820220, 0x3c0308ff, 
+0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0, 0x30c20007, 0x10400003, 
+0x2402fff8, 0xc23024, 0xaf8600e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 
+0x24680008, 0x48102b, 0x10400003, 0x3c02fff5, 0x34421000, 0x1024021, 
+0x8f8b00c8, 0x8f850120, 0x8f840124, 0x8004135, 0x6021, 0x27623800, 
+0x82102b, 0x50400001, 0x27643000, 0x10a40010, 0x318200ff, 0x8c820018, 
+0x38430007, 0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 
+0x24840020, 0x8ee20230, 0x240c0001, 0x24420001, 0xaee20230, 0x8ee20230, 
+0x8c8b0008, 0x318200ff, 0x14400065, 0x0, 0x3c020001, 0x571021, 
+0x904283b0, 0x14400060, 0x0, 0x8f8400e4, 0xc41023, 0x218c3, 
+0x4620001, 0x24630200, 0x8f8900c4, 0x10600005, 0x24020001, 0x10620009, 
+0x0, 0x8004177, 0x0, 0x8ee20220, 0x1205821, 0x24420001, 
+0xaee20220, 0x80041ac, 0x8ee20220, 0x8ee20224, 0x3c05000a, 0x24420001, 
+0xaee20224, 0x8c8b0000, 0x34a5f000, 0x8ee20224, 0x12b1823, 0xa3102b, 
+0x54400001, 0x651821, 0x2c62233f, 0x14400040, 0x0, 0x8f8200e8, 
+0x24420008, 0xaf8200e8, 0x8f8200e8, 0x8f8200e4, 0x1205821, 0x24420008, 
+0xaf8200e4, 0x80041ac, 0x8f8200e4, 0x8ee20228, 0x3c03000a, 0x24420001, 
+0xaee20228, 0x8c840000, 0x3463f000, 0x8ee20228, 0x883823, 0x67102b, 
+0x54400001, 0xe33821, 0x3c020003, 0x34420d40, 0x47102b, 0x10400003, 
+0x0, 0x80041ac, 0x805821, 0x8f8200e4, 0x24440008, 0xaf8400e4, 
+0x8f8400e4, 0x10860018, 0x3c05000a, 0x34a5f000, 0x3c0a0003, 0x354a0d40, 
+0x8ee2007c, 0x24420001, 0xaee2007c, 0x8c830000, 0x8ee2007c, 0x683823, 
+0xa7102b, 0x54400001, 0xe53821, 0x147102b, 0x54400007, 0x605821, 
+0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4, 0x1486ffef, 0x0, 
+0x14860005, 0x0, 0x1205821, 0xaf8600e4, 0x80041ac, 0xaf8600e8, 
+0xaf8400e4, 0xaf8400e8, 0x8f8200c8, 0x3c03000a, 0x3463f000, 0x483823, 
+0x67102b, 0x54400001, 0xe33821, 0x3c020003, 0x34420d3f, 0x47102b, 
+0x54400007, 0x6021, 0x1683823, 0x67102b, 0x54400003, 0xe33821, 
+0x80041bf, 0x3c020003, 0x3c020003, 0x34420d3f, 0x47102b, 0x14400016, 
+0x318200ff, 0x14400006, 0x0, 0x3c020001, 0x571021, 0x904283b0, 
+0x1040000f, 0x0, 0x8ee2022c, 0x3c04fdff, 0x8ee30000, 0x3484ffff, 
+0x24420001, 0xaee2022c, 0x8ee2022c, 0x24020001, 0x641824, 0x3c010001, 
+0x370821, 0xa02283a8, 0x800421c, 0xaee30000, 0xaf8b00c8, 0x8f8300c8, 
+0x8f8200c4, 0x3c04000a, 0x3484f000, 0x623823, 0x87102b, 0x54400001, 
+0xe43821, 0x3c020003, 0x34420d40, 0x47102b, 0x2ce30001, 0x431025, 
+0x10400008, 0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 
+0x3c034000, 0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, 
+0x0, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, 
+0xaf8200e0, 0x3c020001, 0x8c427140, 0x3c030008, 0x8f8600e0, 0x431024, 
+0x1040001d, 0x0, 0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, 
+0x3c0c0080, 0x24850008, 0x27622800, 0x50a20001, 0x27651800, 0x8c880004, 
+0x8c820000, 0x8ca90000, 0x3103ffff, 0x431021, 0x4d1024, 0x24430010, 
+0x6b102b, 0x54400001, 0x6a1821, 0x12b102b, 0x54400001, 0x12a4821, 
+0x10690002, 0x10c1025, 0xac820004, 0xa02021, 0x14c4ffeb, 0x24850008, 
+0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420002, 0xaf820220, 
+0x8f830054, 0x8f820054, 0x8004227, 0x24630001, 0x8f820054, 0x621023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 
+0x431024, 0xaf820220, 0x6010055, 0x0, 0x8ee20218, 0x24420001, 
+0xaee20218, 0x8ee20218, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 
+0x34420004, 0xaf820220, 0x8f830054, 0x8f820054, 0x8004241, 0x24630002, 
+0x8f820054, 0x621023, 0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 
 0x30c20007, 0x10400012, 0x0, 0x8f8300e4, 0x2402fff8, 0xc21024, 
-0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440050, 
-0x8f820054, 0x821023, 0x2c420051, 0x10400004, 0x0, 0x8f8200e0, 
+0x1043000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440032, 
+0x8f820054, 0x821023, 0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 
 0x10c2fff9, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffd, 0x431024, 
 0xaf820220, 0x8f8600e0, 0x30c20007, 0x10400003, 0x2402fff8, 0xc23024, 
-0xaf8600e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 0x24680008, 0x48102b, 
-0x10400003, 0x3c02fff5, 0x34421000, 0x1024021, 0x8f8b00c8, 0x8f850120, 
-0x8f840124, 0x8004091, 0x6021, 0x27623800, 0x82102b, 0x50400001, 
-0x27643000, 0x10a40010, 0x318200ff, 0x8c820018, 0x38430007, 0x2c630001, 
-0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 0x24840020, 0x8ee20230, 
-0x240c0001, 0x24420001, 0xaee20230, 0x8ee20230, 0x8c8b0008, 0x318200ff, 
-0x14400065, 0x0, 0x3c020001, 0x571021, 0x904283b0, 0x14400060, 
-0x0, 0x8f8400e4, 0xc41023, 0x218c3, 0x4620001, 0x24630200, 
-0x8f8900c4, 0x10600005, 0x24020001, 0x10620009, 0x0, 0x80040d3, 
-0x0, 0x8ee20220, 0x1205821, 0x24420001, 0xaee20220, 0x8004108, 
-0x8ee20220, 0x8ee20224, 0x3c05000a, 0x24420001, 0xaee20224, 0x8c8b0000, 
-0x34a5f000, 0x8ee20224, 0x12b1823, 0xa3102b, 0x54400001, 0x651821, 
-0x2c62233f, 0x14400040, 0x0, 0x8f8200e8, 0x24420008, 0xaf8200e8, 
-0x8f8200e8, 0x8f8200e4, 0x1205821, 0x24420008, 0xaf8200e4, 0x8004108, 
-0x8f8200e4, 0x8ee20228, 0x3c03000a, 0x24420001, 0xaee20228, 0x8c840000, 
-0x3463f000, 0x8ee20228, 0x883823, 0x67102b, 0x54400001, 0xe33821, 
-0x3c020003, 0x34420d40, 0x47102b, 0x10400003, 0x0, 0x8004108, 
-0x805821, 0x8f8200e4, 0x24440008, 0xaf8400e4, 0x8f8400e4, 0x10860018, 
-0x3c05000a, 0x34a5f000, 0x3c0a0003, 0x354a0d40, 0x8ee2007c, 0x24420001, 
-0xaee2007c, 0x8c830000, 0x8ee2007c, 0x683823, 0xa7102b, 0x54400001, 
-0xe53821, 0x147102b, 0x54400007, 0x605821, 0x8f8200e4, 0x24440008, 
-0xaf8400e4, 0x8f8400e4, 0x1486ffef, 0x0, 0x14860005, 0x0, 
-0x1205821, 0xaf8600e4, 0x8004108, 0xaf8600e8, 0xaf8400e4, 0xaf8400e8, 
-0x8f8200c8, 0x3c03000a, 0x3463f000, 0x483823, 0x67102b, 0x54400001, 
-0xe33821, 0x3c020003, 0x34420d3f, 0x47102b, 0x54400007, 0x6021, 
-0x1683823, 0x67102b, 0x54400003, 0xe33821, 0x800411b, 0x3c020003, 
-0x3c020003, 0x34420d3f, 0x47102b, 0x14400016, 0x318200ff, 0x14400006, 
-0x0, 0x3c020001, 0x571021, 0x904283b0, 0x1040000f, 0x0, 
-0x8ee2022c, 0x3c04fdff, 0x8ee30000, 0x3484ffff, 0x24420001, 0xaee2022c, 
-0x8ee2022c, 0x24020001, 0x641824, 0x3c010001, 0x370821, 0xa02283a8, 
-0x8004178, 0xaee30000, 0xaf8b00c8, 0x8f8300c8, 0x8f8200c4, 0x3c04000a, 
-0x3484f000, 0x623823, 0x87102b, 0x54400001, 0xe43821, 0x3c020003, 
-0x34420d40, 0x47102b, 0x2ce30001, 0x431025, 0x10400008, 0x0, 
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x3c034000, 0x431025, 
-0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, 0x0, 0x8ee2007c, 
-0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0, 0x3c020001, 
-0x8c426f30, 0x3c030008, 0x8f8600e0, 0x431024, 0x1040001d, 0x0, 
-0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080, 0x24850008, 
-0x27622800, 0x50a20001, 0x27651800, 0x8c880004, 0x8c820000, 0x8ca90000, 
-0x3103ffff, 0x431021, 0x4d1024, 0x24430010, 0x6b102b, 0x54400001, 
-0x6a1821, 0x12b102b, 0x54400001, 0x12a4821, 0x10690002, 0x10c1025, 
-0xac820004, 0xa02021, 0x14c4ffeb, 0x24850008, 0x8f820220, 0x3c0308ff, 
-0x3463ffff, 0x431024, 0x34420002, 0xaf820220, 0x8f830054, 0x8f820054, 
-0x8004183, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 
-0x6010055, 0x0, 0x8ee20218, 0x24420001, 0xaee20218, 0x8ee20218, 
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, 0xaf820220, 
-0x8f830054, 0x8f820054, 0x800419d, 0x24630002, 0x8f820054, 0x621023, 
-0x2c420003, 0x1440fffc, 0x0, 0x8f8600e0, 0x30c20007, 0x10400012, 
-0x0, 0x8f8300e4, 0x2402fff8, 0xc21024, 0x1043000d, 0x0, 
-0x8f820054, 0x8f8300e0, 0x14c30009, 0x24440032, 0x8f820054, 0x821023, 
-0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x10c2fff9, 0x0, 
-0x8f820220, 0x3c0308ff, 0x3463fffd, 0x431024, 0xaf820220, 0x8f8600e0, 
-0x30c20007, 0x10400003, 0x2402fff8, 0xc23024, 0xaf8600e0, 0x240301f5, 
-0x8f8200e8, 0x673823, 0x718c0, 0x431021, 0xaf8200e8, 0x8f8200e8, 
-0xaf8200e4, 0x8ee2007c, 0x3c0408ff, 0x3484ffff, 0x471021, 0xaee2007c, 
-0x8f820220, 0x3c038000, 0x34630002, 0x441024, 0x431025, 0xaf820220, 
-0x8f830054, 0x8f820054, 0x80041d9, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 
-0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 
-0x27bd0028, 0x3c020001, 0x8c424dfc, 0x27bdffd8, 0x10400012, 0xafbf0020, 
-0x3c040001, 0x24844b74, 0x3c050008, 0x24020001, 0x3c010001, 0x370821, 
-0xac22839c, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50498, 0x3c010001, 
-0xac204dfc, 0x3c010001, 0xac224df0, 0xc0023a7, 0x3821, 0x8f420268, 
-0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, 0x8ee204c0, 0x8ee404c4, 
-0x2403fffe, 0x431024, 0x30840002, 0x10800118, 0xaee204c0, 0x8ee204c4, 
-0x2403fffd, 0x431024, 0xaee204c4, 0x8f820044, 0x3c030600, 0x34632000, 
-0x34420020, 0xaf820044, 0xafa30018, 0x8ee205f8, 0x8f430228, 0x24420001, 
-0x304a00ff, 0x514300f8, 0xafa00010, 0x8ee205f8, 0x210c0, 0x571021, 
-0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 0x8f830054, 0x8f820054, 
-0x24690032, 0x1221023, 0x2c420033, 0x10400067, 0x5821, 0x24180008, 
-0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 0x8f870120, 0x27623800, 
-0x24e80020, 0x102102b, 0x50400001, 0x27683000, 0x8f820128, 0x15020007, 
-0x1021, 0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x8004286, 
-0x8ee201a0, 0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 
-0xa32821, 0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 
-0x8ee205f8, 0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 
-0x2e21021, 0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 
-0x14400033, 0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 
-0x8c820000, 0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 
-0x0, 0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 
-0x24420001, 0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 
-0x0, 0x8004273, 0x0, 0x14600005, 0x0, 0x8f820128, 
-0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 
-0xac800000, 0x8004286, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 
-0x1021, 0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 
-0x24425028, 0x2e22021, 0xac8d0000, 0xac8e0004, 0x54a00006, 0x240b0001, 
-0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa0, 0x0, 0x316300ff, 
-0x24020001, 0x54620076, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 
-0x24690032, 0x1221023, 0x2c420033, 0x1040005e, 0x5821, 0x240d0008, 
-0x240c0011, 0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 
-0x24660020, 0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x14c20007, 
-0x0, 0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x80042ef, 
-0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 0x8ee50494, 0x2462001c, 
-0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 0xac650004, 0x8ee204b4, 
-0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 0x24050001, 0x8ee24e20, 
-0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 0x1448001f, 0x0, 
-0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 0x8c820004, 0x24420001, 
-0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 0x10470007, 0x0, 
-0x8ee24e24, 0x24420001, 0x10620005, 0x0, 0x80042dc, 0x0, 
-0x14600005, 0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 
-0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 0x80042ef, 0x0, 
-0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 0x8ee24e20, 0x24420001, 
-0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0xac880000, 
-0xac8a0004, 0x54a00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 
-0x1440ffa9, 0x0, 0x316300ff, 0x24020001, 0x54620003, 0xafa00010, 
-0x800431c, 0x0, 0x3c040001, 0x24844b80, 0xafa00014, 0x8f860120, 
-0x8f870124, 0x3c050009, 0xc0023a7, 0x34a5f011, 0x800431c, 0x0, 
-0x3c040001, 0x24844b8c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 
-0xc0023a7, 0x34a5f010, 0x800431c, 0x0, 0x3c040001, 0x24844b98, 
-0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 0xc0023a7, 0x34a5f00f, 
-0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 0x8ee20158, 0x24420001, 
-0xaee20158, 0x8ee20158, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c020001, 
-0x8c424dfc, 0x27bdffe0, 0x1440000d, 0xafbf0018, 0x3c040001, 0x24844ba4, 
-0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, 0x24020001, 
-0x3c010001, 0xac224dfc, 0xc0023a7, 0x3821, 0x8ee204c0, 0x3c030001, 
-0x771821, 0x946383a2, 0x34420001, 0x10600007, 0xaee204c0, 0x8f820220, 
-0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24040001, 
-0xc004f33, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x3c120001, 0x26520f00, 0x3c140001, 0x8e944d70, 
-0x3c100001, 0x26100e20, 0x3c15c000, 0x36b50060, 0x8e8a0000, 0x8eb30000, 
-0x26a400b, 0x248000a, 0x200f821, 0x0, 0xd, 0x0, 
-0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+0xaf8600e0, 0x240301f5, 0x8f8200e8, 0x673823, 0x718c0, 0x431021, 
+0xaf8200e8, 0x8f8200e8, 0xaf8200e4, 0x8ee2007c, 0x3c0408ff, 0x3484ffff, 
+0x471021, 0xaee2007c, 0x8f820220, 0x3c038000, 0x34630002, 0x441024, 
+0x431025, 0xaf820220, 0x8f830054, 0x8f820054, 0x800427d, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 
+0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 
+0x8fb00018, 0x3e00008, 0x27bd0028, 0x3c020001, 0x8c42500c, 0x27bdffd8, 
+0x10400012, 0xafbf0020, 0x3c040001, 0x24844d84, 0x3c050008, 0x24020001, 
+0x3c010001, 0x370821, 0xac22839c, 0xafa00010, 0xafa00014, 0x8f860220, 
+0x34a50498, 0x3c010001, 0xac20500c, 0x3c010001, 0xac225000, 0xc002403, 
+0x3821, 0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, 
+0x8ee204c0, 0x8ee404c4, 0x2403fffe, 0x431024, 0x30840002, 0x1080011e, 
+0xaee204c0, 0x8ee204c4, 0x2403fffd, 0x431024, 0xaee204c4, 0x8f820044, 
+0x3c030600, 0x34632000, 0x34420020, 0xaf820044, 0xafa30018, 0x8ee205f8, 
+0x8f430228, 0x24420001, 0x304a00ff, 0x514300fe, 0xafa00010, 0x8ee205f8, 
+0x210c0, 0x571021, 0x8fa30018, 0x8fa4001c, 0xac4305fc, 0xac440600, 
+0x8f830054, 0x8f820054, 0x24690032, 0x1221023, 0x2c420033, 0x1040006a, 
+0x5821, 0x24180008, 0x240f000d, 0x240d0007, 0x240c0040, 0x240e0001, 
+0x8f870120, 0x27623800, 0x24e80020, 0x102102b, 0x50400001, 0x27683000, 
+0x8f820128, 0x11020004, 0x0, 0x8f820124, 0x15020007, 0x1021, 
+0x8ee201a0, 0x2821, 0x24420001, 0xaee201a0, 0x800432d, 0x8ee201a0, 
+0x8ee405f8, 0x420c0, 0x801821, 0x8ee40430, 0x8ee50434, 0xa32821, 
+0xa3302b, 0x822021, 0x862021, 0xace40000, 0xace50004, 0x8ee205f8, 
+0xa4f8000e, 0xacef0018, 0xacea001c, 0x210c0, 0x244205fc, 0x2e21021, 
+0xace20008, 0x8ee204b4, 0xace20010, 0xaf880120, 0x92e24e10, 0x14400033, 
+0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
+0x144d001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
+0x104c0007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
+0x800431a, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 
+0x800432d, 0x0, 0x8ee24e20, 0x24420001, 0x504c0003, 0x1021, 
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0xac8d0000, 0xac8e0004, 0x54a00006, 0x240b0001, 0x8f820054, 
+0x1221023, 0x2c420033, 0x1440ff9d, 0x0, 0x316300ff, 0x24020001, 
+0x54620079, 0xafa00010, 0xaeea05f8, 0x8f830054, 0x8f820054, 0x24690032, 
+0x1221023, 0x2c420033, 0x10400061, 0x5821, 0x240d0008, 0x240c0011, 
+0x24080012, 0x24070040, 0x240a0001, 0x8f830120, 0x27623800, 0x24660020, 
+0xc2102b, 0x50400001, 0x27663000, 0x8f820128, 0x10c20004, 0x0, 
+0x8f820124, 0x14c20007, 0x0, 0x8ee201a0, 0x2821, 0x24420001, 
+0xaee201a0, 0x8004399, 0x8ee201a0, 0x8ee205f8, 0xac62001c, 0x8ee40490, 
+0x8ee50494, 0x2462001c, 0xac620008, 0xa46d000e, 0xac6c0018, 0xac640000, 
+0xac650004, 0x8ee204b4, 0xac620010, 0xaf860120, 0x92e24e10, 0x14400033, 
+0x24050001, 0x8ee24e20, 0x210c0, 0x24425028, 0x2e22021, 0x8c820000, 
+0x1448001f, 0x0, 0x8ee34e20, 0x8ee24e24, 0x1062001b, 0x0, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ee24e24, 0x8ee34e20, 0x24420001, 
+0x10470007, 0x0, 0x8ee24e24, 0x24420001, 0x10620005, 0x0, 
+0x8004386, 0x0, 0x14600005, 0x0, 0x8f820128, 0x24420020, 
+0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400010, 0xac800000, 
+0x8004399, 0x0, 0x8ee24e20, 0x24420001, 0x50470003, 0x1021, 
+0x8ee24e20, 0x24420001, 0xaee24e20, 0x8ee24e20, 0x210c0, 0x24425028, 
+0x2e22021, 0xac880000, 0xac8a0004, 0x54a00006, 0x240b0001, 0x8f820054, 
+0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 
+0x54620003, 0xafa00010, 0x80043c6, 0x0, 0x3c040001, 0x24844d90, 
+0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 
+0x80043c6, 0x0, 0x3c040001, 0x24844d9c, 0xafa00014, 0x8f860120, 
+0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80043c6, 0x0, 
+0x3c040001, 0x24844da8, 0xafa00014, 0x8ee605f8, 0x8f470228, 0x3c050009, 
+0xc002403, 0x34a5f00f, 0x8ee201a8, 0x24420001, 0xaee201a8, 0x8ee201a8, 
+0x8ee20158, 0x24420001, 0xaee20158, 0x8ee20158, 0x8fbf0020, 0x3e00008, 
+0x27bd0028, 0x3c020001, 0x8c42500c, 0x27bdffe0, 0x1440000d, 0xafbf0018, 
+0x3c040001, 0x24844db4, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 
+0x34a50499, 0x24020001, 0x3c010001, 0xac22500c, 0xc002403, 0x3821, 
+0x8ee204c0, 0x3c030001, 0x771821, 0x946383a2, 0x34420001, 0x10600007, 
+0xaee204c0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 
+0xaf820220, 0x24040001, 0xc004fb3, 0x24050004, 0xaf420268, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x0, 0x0, 0x3c120001, 0x26521100, 
+0x3c140001, 0x8e944f80, 0x3c100001, 0x26101020, 0x3c15c000, 0x36b50060, 
+0x8e8a0000, 0x8eb30000, 0x26a400b, 0x248000a, 0x200f821, 0x0, 
+0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x80014c4, 0x0, 0x80014c6, 0x3c0a0001, 0x80014c6, 0x3c0a0002, 
-0x80014c6, 0x0, 0x800244a, 0x0, 0x80014c6, 0x3c0a0003, 
-0x80014c6, 0x3c0a0004, 0x8002ef8, 0x0, 0x80014c6, 0x3c0a0005, 
-0x8003c3d, 0x0, 0x8003bbe, 0x0, 0x80014c6, 0x3c0a0006, 
-0x80014c6, 0x3c0a0007, 0x80014c6, 0x0, 0x80014c6, 0x0, 
-0x80014c6, 0x0, 0x80029f8, 0x0, 0x80014c6, 0x3c0a000b, 
-0x80014c6, 0x3c0a000c, 0x80014c6, 0x3c0a000d, 0x800231c, 0x0, 
-0x80022d9, 0x0, 0x80014c6, 0x3c0a000e, 0x8001b08, 0x0, 
-0x8002448, 0x0, 0x80014c6, 0x3c0a000f, 0x8003ff3, 0x0, 
-0x8003fdd, 0x0, 0x80014c6, 0x3c0a0010, 0x80014da, 0x0, 
-0x80014c6, 0x3c0a0011, 0x80014c6, 0x3c0a0012, 0x80014c6, 0x3c0a0013, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
+0x0, 0x0, 0x80014d6, 0x0, 0x80014d8, 0x3c0a0001, 
+0x80014d8, 0x3c0a0002, 0x80014d8, 0x0, 0x80024a6, 0x0, 
+0x80014d8, 0x3c0a0003, 0x80014d8, 0x3c0a0004, 0x8002f7c, 0x0, 
+0x80014d8, 0x3c0a0005, 0x8003cd8, 0x0, 0x8003c56, 0x0, 
+0x80014d8, 0x3c0a0006, 0x80014d8, 0x3c0a0007, 0x80014d8, 0x0, 
+0x80014d8, 0x0, 0x80014d8, 0x0, 0x8002a75, 0x0, 
+0x80014d8, 0x3c0a000b, 0x80014d8, 0x3c0a000c, 0x80014d8, 0x3c0a000d, 
+0x8002378, 0x0, 0x8002335, 0x0, 0x80014d8, 0x3c0a000e, 
+0x8001b38, 0x0, 0x80024a4, 0x0, 0x80014d8, 0x3c0a000f, 
+0x8004097, 0x0, 0x8004081, 0x0, 0x80014d8, 0x3c0a0010, 
+0x80014ee, 0x0, 0x80014d8, 0x3c0a0011, 0x80014d8, 0x3c0a0012, 
+0x80014d8, 0x3c0a0013, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
@@ -2243,541 +2264,542 @@
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x0, 0x0, 0x3c030001, 0x34633800, 0x24050080, 0x2404001f, 
-0x2406ffff, 0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 0x3631021, 
-0xaf8200c0, 0x3631021, 0xaf8200c4, 0x3631021, 0xaf8200c8, 0x27623800, 
-0xaf8200d0, 0x27623800, 0xaf8200d4, 0x27623800, 0xaf8200d8, 0x27621800, 
-0xaf8200e0, 0x27621800, 0xaf8200e4, 0x27621800, 0xaf8200e8, 0x27621000, 
-0xaf8200f0, 0x27621000, 0xaf8200f4, 0x27621000, 0xaf8200f8, 0xaca00000, 
-0x2484ffff, 0x1486fffd, 0x24a50004, 0x8f830040, 0x3c02f000, 0x621824, 
-0x3c025000, 0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 
-0x10620008, 0x24020800, 0x8004479, 0x0, 0x10620004, 0x24020800, 
-0x8004479, 0x0, 0x24020700, 0x3c010001, 0xac224e00, 0x3e00008, 
-0x0, 0x27bdffd0, 0xafbf0028, 0x3c010001, 0xc004b65, 0xac204de8, 
-0x24040001, 0x2821, 0x27a60020, 0x34028000, 0xc004782, 0xa7a20020, 
-0x8f830054, 0x8f820054, 0x800448b, 0x24630064, 0x8f820054, 0x621023, 
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004740, 0x27a60020, 
-0x8f830054, 0x8f820054, 0x8004497, 0x24630064, 0x8f820054, 0x621023, 
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004740, 0x27a60020, 
-0x8f830054, 0x8f820054, 0x80044a3, 0x24630064, 0x8f820054, 0x621023, 
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 0xc004740, 0x27a60018, 
-0x8f830054, 0x8f820054, 0x80044af, 0x24630064, 0x8f820054, 0x621023, 
-0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 0xc004740, 0x27a6001a, 
-0x97a20020, 0x10400022, 0x24030001, 0x3c020001, 0x8c424de8, 0x97a30018, 
-0x34420001, 0x3c010001, 0xac224de8, 0x24020015, 0x14620008, 0x3402f423, 
-0x97a3001a, 0x14620005, 0x24020003, 0x3c010001, 0xac224e9c, 0x80044e2, 
-0x3c08fff0, 0x97a30018, 0x24027810, 0x1462000a, 0x24020002, 0x97a3001a, 
-0x24020001, 0x14620006, 0x24020002, 0x24020004, 0x3c010001, 0xac224e9c, 
-0x80044e2, 0x3c08fff0, 0x3c010001, 0xac224e9c, 0x80044e2, 0x3c08fff0, 
-0x3c020001, 0x8c424de8, 0x3c010001, 0xac234e9c, 0x34420004, 0x3c010001, 
-0xac224de8, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, 
-0x8ce74e9c, 0x3c040001, 0x24844c10, 0x24020001, 0x3c010001, 0xac224df0, 
-0xafa60010, 0x3c060001, 0x8cc64de8, 0x97a2001a, 0x3c05000d, 0x34a50100, 
-0x3c010001, 0xac204dec, 0x681821, 0x3c010001, 0xac234e94, 0xc0023a7, 
-0xafa20014, 0x8fbf0028, 0x3e00008, 0x27bd0030, 0x27bdffe8, 0x24070004, 
-0x3c040001, 0x8c844dec, 0x3021, 0x24020001, 0x1482000a, 0xafbf0010, 
-0x3c020001, 0x8c426f3c, 0x3c050004, 0x30428000, 0x1040000c, 0x34a593e0, 
-0x3c05000f, 0x8004515, 0x34a54240, 0x3c020001, 0x8c426f3c, 0x3c05000f, 
-0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480, 0x3c020001, 
-0x8c424e94, 0x8f830054, 0x451021, 0x431023, 0x45102b, 0x1440002e, 
-0x0, 0x3c020001, 0x8c424df4, 0x1440002a, 0x2cc20001, 0x7182b, 
-0x431024, 0x1040001d, 0x0, 0x3c090001, 0x8d294de8, 0x240b0001, 
-0x3c054000, 0x3c080001, 0x25086f3c, 0x250afffc, 0x42042, 0x14800002, 
-0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 0x2cc20001, 0x148b0004, 
-0x0, 0x8d020000, 0x800453a, 0x451024, 0x8d420000, 0x451024, 
-0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 0x431024, 0x5440ffed, 
-0x42042, 0x3c010001, 0x10c00024, 0xac244dec, 0x8f830054, 0x24020001, 
-0x3c010001, 0xac224df0, 0x3c010001, 0xac234e94, 0x3c020001, 0x8c424df0, 
-0x10400006, 0x24020001, 0x3c010001, 0xac204df0, 0x3c010001, 0x370821, 
-0xac22839c, 0x3c030001, 0x771821, 0x8c63839c, 0x24020008, 0x10620005, 
-0x24020001, 0xc00456a, 0x0, 0x8004567, 0x0, 0x3c030001, 
-0x8c634dec, 0x10620007, 0x2402000e, 0x3c030001, 0x8c636eb0, 0x10620003, 
-0x0, 0xc004b88, 0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
-0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, 0x3c050001, 0x8ca54dec, 
-0x3c040001, 0x8c844e04, 0x3442ffff, 0x621824, 0x14a40008, 0xaee30000, 
-0x3c030001, 0x771821, 0x8c63839c, 0x3c020001, 0x8c424e08, 0x10620008, 
-0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x3c010001, 0xac254e04, 
-0x3c010001, 0xac224e08, 0x3c030001, 0x8c634dec, 0x24020002, 0x10620126, 
-0x2c620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x80046ae, 
-0x0, 0x24020004, 0x1062007c, 0x24020001, 0x80046af, 0x0, 
-0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 0x2c620008, 0x10400117, 
-0x31080, 0x3c010001, 0x220821, 0x8c224c28, 0x400008, 0x0, 
-0xc0046b4, 0x0, 0x3c020001, 0x8c424df8, 0x3c010001, 0xac204d80, 
-0x104000c5, 0x24020002, 0x3c010001, 0x370821, 0xac22839c, 0x3c010001, 
-0x80046b1, 0xac204df8, 0xc0047c3, 0x0, 0x3c030001, 0x8c634e10, 
-0x24020011, 0x146200fd, 0x24020003, 0x8004631, 0x0, 0x3c050001, 
-0x8ca54dec, 0x3c060001, 0x8cc66f3c, 0xc004e2c, 0x24040001, 0x24020005, 
-0x3c010001, 0xac204df8, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 
-0x3c040001, 0x24844c1c, 0x3c05000f, 0x34a50100, 0x3021, 0x3821, 
-0xafa00010, 0xc0023a7, 0xafa00014, 0x80046b1, 0x0, 0x8f820220, 
-0x3c03f700, 0x431025, 0x8004658, 0xaf820220, 0x8f820220, 0x3c030004, 
-0x431024, 0x14400095, 0x24020007, 0x8f830054, 0x3c020001, 0x8c424e90, 
-0x2463d8f0, 0x431023, 0x2c422710, 0x144000d1, 0x24020001, 0x80046af, 
-0x0, 0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 0xc004ff8, 
-0x24040001, 0x3c030001, 0x8c636f34, 0x46100c3, 0x24020001, 0x3c020008, 
-0x621024, 0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 0x431024, 
-0x80045fa, 0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, 
-0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, 0x8f820220, 
-0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 
-0x24020008, 0x3c010001, 0x370821, 0xc004323, 0xac22839c, 0x80046b1, 
-0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 0x2c620008, 
-0x1040009e, 0x31080, 0x3c010001, 0x220821, 0x8c224c48, 0x400008, 
-0x0, 0xc0041e7, 0x0, 0x3c010001, 0xac204df0, 0xaf800204, 
-0x3c010001, 0xc0046b4, 0xac206f00, 0x8f820044, 0x34428080, 0xaf820044, 
-0x8f830054, 0x3c010001, 0xac204d80, 0x800465a, 0x24020002, 0x8f830054, 
-0x3c020001, 0x8c424e90, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400081, 
-0x24020003, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 0x3c020001, 
-0x8c426f38, 0x30424000, 0x10400005, 0x0, 0x8f820044, 0x3c03ffff, 
-0x8004640, 0x34637fff, 0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044, 
-0x8f830054, 0x800465a, 0x24020004, 0x8f830054, 0x3c020001, 0x8c424e90, 
-0x2463d8f0, 0x431023, 0x2c422710, 0x14400065, 0x24020005, 0x3c010001, 
-0x370821, 0x80046b1, 0xac22839c, 0x8f820220, 0x3c03f700, 0x431025, 
-0xaf820220, 0xaf800204, 0x3c010001, 0xac206f00, 0x8f830054, 0x24020006, 
-0x3c010001, 0x370821, 0xac22839c, 0x3c010001, 0x80046b1, 0xac234e90, 
-0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, 0x3c030001, 0x8c634e90, 
-0x3484869f, 0x451021, 0x621823, 0x83202b, 0x10800046, 0x0, 
-0x24020007, 0x3c010001, 0x370821, 0x80046b1, 0xac22839c, 0x8f820220, 
-0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 0x3c030300, 0x431024, 
-0x14400005, 0x1821, 0x8f820220, 0x24030001, 0x441025, 0xaf820220, 
-0x10600030, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c844e88, 
-0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x3c010001, 0x370821, 
-0xac22839c, 0x10800007, 0x24020001, 0x3c010001, 0xac226eb0, 0xc004b88, 
-0x8f840220, 0x80046b1, 0x0, 0x8f820220, 0x3c030008, 0x431024, 
-0x1440001a, 0x2402000e, 0x3c010001, 0xac226eb0, 0x8ee20000, 0x24040001, 
-0x3c030200, 0x431025, 0xc004ff8, 0xaee20000, 0x8f820220, 0x2403fffb, 
-0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xc004323, 0xaf820220, 
-0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 0x80046b1, 0x0, 
-0x24020001, 0x3c010001, 0xac224df0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
-0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820200, 
-0x3c060001, 0x8cc64dec, 0x34420004, 0xaf820200, 0x24020002, 0x10c20048, 
-0x2cc20003, 0x10400005, 0x24020001, 0x10c20008, 0x0, 0x8004708, 
-0x0, 0x24020004, 0x10c20013, 0x24020001, 0x8004708, 0x0, 
-0x3c030001, 0x8c634dd8, 0x3c020001, 0x8c424de4, 0x3c040001, 0x8c844e00, 
-0x3c050001, 0x8ca54ddc, 0xaf860200, 0xaf860220, 0x34630022, 0x441025, 
-0x451025, 0x34420002, 0x8004707, 0xaf830200, 0xaf820200, 0xaf820220, 
-0x8f820044, 0x3c030001, 0x8c634e88, 0x34428080, 0xaf820044, 0x10600005, 
-0x3c033f00, 0x3c020001, 0x8c424dd0, 0x80046fb, 0x346300e0, 0x8f8400f0, 
-0x276217f8, 0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, 0x10a20007, 
-0x3c038000, 0x34630040, 0x3c020001, 0x24424d90, 0xac820000, 0xac830004, 
-0xaf8500f0, 0x3c020001, 0x8c424dd0, 0x3c033f00, 0x346300e2, 0x431025, 
-0xaf820200, 0x3c030001, 0x8c634dd4, 0x3c04f700, 0x3c020001, 0x8c424de4, 
-0x3c050001, 0x8ca54e00, 0x641825, 0x431025, 0x451025, 0xaf820220, 
-0x3e00008, 0x0, 0x8f820220, 0x3c030001, 0x8c634dec, 0x34420004, 
-0xaf820220, 0x24020001, 0x1062000f, 0x0, 0x8f830054, 0x8f820054, 
-0x24630002, 0x621023, 0x2c420003, 0x10400011, 0x0, 0x8f820054, 
-0x621023, 0x2c420003, 0x1040000c, 0x0, 0x8004719, 0x0, 
-0x8f830054, 0x8f820054, 0x8004725, 0x24630007, 0x8f820054, 0x621023, 
-0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0, 0x30820007, 0x1040000d, 
-0x0, 0x8f820054, 0x8f8300e0, 0x14830009, 0x24450032, 0x8f820054, 
-0xa21023, 0x2c420033, 0x10400004, 0x0, 0x8f8200e0, 0x1082fff9, 
-0x0, 0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, 0x3e00008, 
-0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c, 
-0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, 0xafbf0020, 
-0xa6200000, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x2021, 0x24100010, 0x2501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x2501024, 
-0x24100010, 0x2701024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fffa, 0x2701024, 0xc004b65, 0x34108000, 0xc004b65, 
-0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000, 
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65, 
-0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 
-0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018, 
-0xa09021, 0xafb3001c, 0xc09821, 0xafb00010, 0x8021, 0xafbf0020, 
-0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
-0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 
-0xc004b3f, 0x24040001, 0x24100010, 0x2301024, 0x10400002, 0x2021, 
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x2301024, 0x24100010, 
-0x2501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 
-0x1600fffa, 0x2501024, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 
-0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, 0x24040001, 
-0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 
-0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 
-0x27bd0028, 0x3c030001, 0x8c634e10, 0x3c020001, 0x8c424e54, 0x27bdffd8, 
-0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001, 0xac234e54, 
-0x2463ffff, 0x2c620013, 0x10400349, 0x31080, 0x3c010001, 0x220821, 
-0x8c224c70, 0x400008, 0x0, 0xc004b65, 0x8021, 0x34028000, 
-0xa7a20010, 0x27b10010, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 
-0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 
-0x32020001, 0x24100010, 0xc004b3f, 0x2021, 0x108042, 0x1600fffc, 
-0x0, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, 
-0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8004b18, 
-0x24020002, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 
-0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 
-0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004b3f, 0x2021, 
-0x108042, 0x1600fffc, 0x0, 0xc004b65, 0x34108000, 0xc004b65, 
-0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000, 
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65, 
-0x0, 0x97a20010, 0x30428000, 0x144002dc, 0x24020003, 0x8004b18, 
-0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, 0xc004b3f, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 
-0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004b3f, 
-0x2021, 0x108042, 0x1600fffc, 0x0, 0xc004b3f, 0x24040001, 
-0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 
-0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x24020004, 0x8f830054, 
-0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 
-0x24020002, 0x3c030001, 0x8c634e9c, 0x10620297, 0x2c620003, 0x14400296, 
-0x24020011, 0x24020003, 0x10620005, 0x24020004, 0x10620291, 0x2402000f, 
-0x8004b18, 0x24020011, 0x8004b18, 0x24020005, 0x24020014, 0xa7a20010, 
-0x27b10010, 0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 
-0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 
-0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 
-0x32020001, 0x24100010, 0x32020012, 0x10400002, 0x2021, 0x24040001, 
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020012, 0xc004b3f, 0x24040001, 
-0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 
-0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x24020006, 0x8f830054, 
-0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, 
-0x24020007, 0x8004b18, 0x0, 0x24020006, 0xa7a20010, 0x27b10010, 
-0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 
-0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 
-0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fffa, 0x32020013, 0xc004b3f, 0x24040001, 0xc004b3f, 
+0x0, 0x0, 0x0, 0x0, 0x3c030001, 0x34633800, 
+0x24050080, 0x2404001f, 0x2406ffff, 0x24020001, 0xaf80021c, 0xaf820200, 
+0xaf820220, 0x3631021, 0xaf8200c0, 0x3631021, 0xaf8200c4, 0x3631021, 
+0xaf8200c8, 0x27623800, 0xaf8200d0, 0x27623800, 0xaf8200d4, 0x27623800, 
+0xaf8200d8, 0x27621800, 0xaf8200e0, 0x27621800, 0xaf8200e4, 0x27621800, 
+0xaf8200e8, 0x27621000, 0xaf8200f0, 0x27621000, 0xaf8200f4, 0x27621000, 
+0xaf8200f8, 0xaca00000, 0x2484ffff, 0x1486fffd, 0x24a50004, 0x8f830040, 
+0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 0x43102b, 0x14400006, 
+0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x80044f9, 0x0, 
+0x10620004, 0x24020800, 0x80044f9, 0x0, 0x24020700, 0x3c010001, 
+0xac225010, 0x3e00008, 0x0, 0x27bdffd0, 0xafbf0028, 0x3c010001, 
+0xc004be5, 0xac204ff8, 0x24040001, 0x2821, 0x27a60020, 0x34028000, 
+0xc004802, 0xa7a20020, 0x8f830054, 0x8f820054, 0x800450b, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 
+0xc0047c0, 0x27a60020, 0x8f830054, 0x8f820054, 0x8004517, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 
+0xc0047c0, 0x27a60020, 0x8f830054, 0x8f820054, 0x8004523, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 
+0xc0047c0, 0x27a60018, 0x8f830054, 0x8f820054, 0x800452f, 0x24630064, 
+0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 
+0xc0047c0, 0x27a6001a, 0x97a20020, 0x10400022, 0x24030001, 0x3c020001, 
+0x8c424ff8, 0x97a30018, 0x34420001, 0x3c010001, 0xac224ff8, 0x24020015, 
+0x14620008, 0x3402f423, 0x97a3001a, 0x14620005, 0x24020003, 0x3c010001, 
+0xac2250ac, 0x8004562, 0x3c08fff0, 0x97a30018, 0x24027810, 0x1462000a, 
+0x24020002, 0x97a3001a, 0x24020001, 0x14620006, 0x24020002, 0x24020004, 
+0x3c010001, 0xac2250ac, 0x8004562, 0x3c08fff0, 0x3c010001, 0xac2250ac, 
+0x8004562, 0x3c08fff0, 0x3c020001, 0x8c424ff8, 0x3c010001, 0xac2350ac, 
+0x34420004, 0x3c010001, 0xac224ff8, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 
+0x97a60018, 0x3c070001, 0x8ce750ac, 0x3c040001, 0x24844e20, 0x24020001, 
+0x3c010001, 0xac225000, 0xafa60010, 0x3c060001, 0x8cc64ff8, 0x97a2001a, 
+0x3c05000d, 0x34a50100, 0x3c010001, 0xac204ffc, 0x681821, 0x3c010001, 
+0xac2350a4, 0xc002403, 0xafa20014, 0x8fbf0028, 0x3e00008, 0x27bd0030, 
+0x27bdffe8, 0x24070004, 0x3c040001, 0x8c844ffc, 0x3021, 0x24020001, 
+0x1482000a, 0xafbf0010, 0x3c020001, 0x8c42714c, 0x3c050004, 0x30428000, 
+0x1040000c, 0x34a593e0, 0x3c05000f, 0x8004595, 0x34a54240, 0x3c020001, 
+0x8c42714c, 0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 
+0x34a58480, 0x3c020001, 0x8c4250a4, 0x8f830054, 0x451021, 0x431023, 
+0x45102b, 0x1440002e, 0x0, 0x3c020001, 0x8c425004, 0x1440002a, 
+0x2cc20001, 0x7182b, 0x431024, 0x1040001d, 0x0, 0x3c090001, 
+0x8d294ff8, 0x240b0001, 0x3c054000, 0x3c080001, 0x2508714c, 0x250afffc, 
+0x42042, 0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 
+0x2cc20001, 0x148b0004, 0x0, 0x8d020000, 0x80045ba, 0x451024, 
+0x8d420000, 0x451024, 0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 
+0x431024, 0x5440ffed, 0x42042, 0x3c010001, 0x10c00024, 0xac244ffc, 
+0x8f830054, 0x24020001, 0x3c010001, 0xac225000, 0x3c010001, 0xac2350a4, 
+0x3c020001, 0x8c425000, 0x10400006, 0x24020001, 0x3c010001, 0xac205000, 
+0x3c010001, 0x370821, 0xac22839c, 0x3c030001, 0x771821, 0x8c63839c, 
+0x24020008, 0x10620005, 0x24020001, 0xc0045ea, 0x0, 0x80045e7, 
+0x0, 0x3c030001, 0x8c634ffc, 0x10620007, 0x2402000e, 0x3c030001, 
+0x8c6370c0, 0x10620003, 0x0, 0xc004c08, 0x8f840220, 0x8fbf0010, 
+0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, 
+0x3c050001, 0x8ca54ffc, 0x3c040001, 0x8c845014, 0x3442ffff, 0x621824, 
+0x14a40008, 0xaee30000, 0x3c030001, 0x771821, 0x8c63839c, 0x3c020001, 
+0x8c425018, 0x10620008, 0x0, 0x3c020001, 0x571021, 0x8c42839c, 
+0x3c010001, 0xac255014, 0x3c010001, 0xac225018, 0x3c030001, 0x8c634ffc, 
+0x24020002, 0x10620126, 0x2c620003, 0x10400005, 0x24020001, 0x10620008, 
+0x0, 0x800472e, 0x0, 0x24020004, 0x1062007c, 0x24020001, 
+0x800472f, 0x0, 0x3c020001, 0x571021, 0x8c42839c, 0x2443ffff, 
+0x2c620008, 0x10400117, 0x31080, 0x3c010001, 0x220821, 0x8c224e38, 
+0x400008, 0x0, 0xc004734, 0x0, 0x3c020001, 0x8c425008, 
+0x3c010001, 0xac204f90, 0x104000c5, 0x24020002, 0x3c010001, 0x370821, 
+0xac22839c, 0x3c010001, 0x8004731, 0xac205008, 0xc004843, 0x0, 
+0x3c030001, 0x8c635020, 0x24020011, 0x146200fd, 0x24020003, 0x80046b1, 
+0x0, 0x3c050001, 0x8ca54ffc, 0x3c060001, 0x8cc6714c, 0xc004eac, 
+0x24040001, 0x24020005, 0x3c010001, 0xac205008, 0x3c010001, 0x370821, 
+0x8004731, 0xac22839c, 0x3c040001, 0x24844e2c, 0x3c05000f, 0x34a50100, 
+0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x8004731, 
+0x0, 0x8f820220, 0x3c03f700, 0x431025, 0x80046d8, 0xaf820220, 
+0x8f820220, 0x3c030004, 0x431024, 0x14400095, 0x24020007, 0x8f830054, 
+0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000d1, 
+0x24020001, 0x800472f, 0x0, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 
+0x24040001, 0xc005078, 0x24040001, 0x3c030001, 0x8c637144, 0x46100c3, 
+0x24020001, 0x3c020008, 0x621024, 0x10400006, 0x0, 0x8f820214, 
+0x3c03ffff, 0x431024, 0x800467a, 0x3442251f, 0x8f820214, 0x3c03ffff, 
+0x431024, 0x3442241f, 0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, 
+0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 
+0x34420002, 0xaf820220, 0x24020008, 0x3c010001, 0x370821, 0xc0043cd, 
+0xac22839c, 0x8004731, 0x0, 0x3c020001, 0x571021, 0x8c42839c, 
+0x2443ffff, 0x2c620008, 0x1040009e, 0x31080, 0x3c010001, 0x220821, 
+0x8c224e58, 0x400008, 0x0, 0xc00428b, 0x0, 0x3c010001, 
+0xac205000, 0xaf800204, 0x3c010001, 0xc004734, 0xac207110, 0x8f820044, 
+0x34428080, 0xaf820044, 0x8f830054, 0x3c010001, 0xac204f90, 0x80046da, 
+0x24020002, 0x8f830054, 0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 
+0x2c422710, 0x14400081, 0x24020003, 0x3c010001, 0x370821, 0x8004731, 
+0xac22839c, 0x3c020001, 0x8c427148, 0x30424000, 0x10400005, 0x0, 
+0x8f820044, 0x3c03ffff, 0x80046c0, 0x34637fff, 0x8f820044, 0x2403ff7f, 
+0x431024, 0xaf820044, 0x8f830054, 0x80046da, 0x24020004, 0x8f830054, 
+0x3c020001, 0x8c4250a0, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400065, 
+0x24020005, 0x3c010001, 0x370821, 0x8004731, 0xac22839c, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, 0x3c010001, 0xac207110, 
+0x8f830054, 0x24020006, 0x3c010001, 0x370821, 0xac22839c, 0x3c010001, 
+0x8004731, 0xac2350a0, 0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, 
+0x3c030001, 0x8c6350a0, 0x3484869f, 0x451021, 0x621823, 0x83202b, 
+0x10800046, 0x0, 0x24020007, 0x3c010001, 0x370821, 0x8004731, 
+0xac22839c, 0x8f820220, 0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 
+0x3c030300, 0x431024, 0x14400005, 0x1821, 0x8f820220, 0x24030001, 
+0x441025, 0xaf820220, 0x10600030, 0x24020001, 0x8f820214, 0x3c03ffff, 
+0x3c040001, 0x8c845098, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, 
+0x3c010001, 0x370821, 0xac22839c, 0x10800007, 0x24020001, 0x3c010001, 
+0xac2270c0, 0xc004c08, 0x8f840220, 0x8004731, 0x0, 0x8f820220, 
+0x3c030008, 0x431024, 0x1440001a, 0x2402000e, 0x3c010001, 0xac2270c0, 
+0x8ee20000, 0x24040001, 0x3c030200, 0x431025, 0xc005078, 0xaee20000, 
+0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, 
+0xc0043cd, 0xaf820220, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 0x24040001, 
+0x8004731, 0x0, 0x24020001, 0x3c010001, 0xac225000, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 
+0xaf820220, 0x8f820200, 0x3c060001, 0x8cc64ffc, 0x34420004, 0xaf820200, 
+0x24020002, 0x10c20048, 0x2cc20003, 0x10400005, 0x24020001, 0x10c20008, 
+0x0, 0x8004788, 0x0, 0x24020004, 0x10c20013, 0x24020001, 
+0x8004788, 0x0, 0x3c030001, 0x8c634fe8, 0x3c020001, 0x8c424ff4, 
+0x3c040001, 0x8c845010, 0x3c050001, 0x8ca54fec, 0xaf860200, 0xaf860220, 
+0x34630022, 0x441025, 0x451025, 0x34420002, 0x8004787, 0xaf830200, 
+0xaf820200, 0xaf820220, 0x8f820044, 0x3c030001, 0x8c635098, 0x34428080, 
+0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 0x8c424fe0, 0x800477b, 
+0x346300e0, 0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, 0x27651000, 
+0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, 0x24424fa0, 
+0xac820000, 0xac830004, 0xaf8500f0, 0x3c020001, 0x8c424fe0, 0x3c033f00, 
+0x346300e2, 0x431025, 0xaf820200, 0x3c030001, 0x8c634fe4, 0x3c04f700, 
+0x3c020001, 0x8c424ff4, 0x3c050001, 0x8ca55010, 0x641825, 0x431025, 
+0x451025, 0xaf820220, 0x3e00008, 0x0, 0x8f820220, 0x3c030001, 
+0x8c634ffc, 0x34420004, 0xaf820220, 0x24020001, 0x1062000f, 0x0, 
+0x8f830054, 0x8f820054, 0x24630002, 0x621023, 0x2c420003, 0x10400011, 
+0x0, 0x8f820054, 0x621023, 0x2c420003, 0x1040000c, 0x0, 
+0x8004799, 0x0, 0x8f830054, 0x8f820054, 0x80047a5, 0x24630007, 
+0x8f820054, 0x621023, 0x2c420008, 0x1440fffc, 0x0, 0x8f8400e0, 
+0x30820007, 0x1040000d, 0x0, 0x8f820054, 0x8f8300e0, 0x14830009, 
+0x24450032, 0x8f820054, 0xa21023, 0x2c420033, 0x10400004, 0x0, 
+0x8f8200e0, 0x1082fff9, 0x0, 0x8f820220, 0x2403fffd, 0x431024, 
+0xaf820220, 0x3e00008, 0x0, 0x0, 0x27bdffd8, 0xafb20018, 
+0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 
+0x8021, 0xafbf0020, 0xa6200000, 0xc004bbf, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010, 
+0x2501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, 0x2021, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x2701024, 0xc004be5, 
+0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, 
+0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
+0x0, 0xc004be5, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 
+0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 
+0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, 0xafb00010, 
+0x8021, 0xafbf0020, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 
+0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 
+0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x2301024, 
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 
+0x2301024, 0x24100010, 0x2501024, 0x10400002, 0x2021, 0x24040001, 
+0xc004bbf, 0x108042, 0x1600fffa, 0x2501024, 0xc004bbf, 0x24040001, 
+0xc004bbf, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002, 
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 
+0xc004be5, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 
+0x8fb00010, 0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635020, 0x3c020001, 
+0x8c425064, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, 
+0x3c010001, 0xac235064, 0x2463ffff, 0x2c620013, 0x10400349, 0x31080, 
+0x3c010001, 0x220821, 0x8c224e80, 0x400008, 0x0, 0xc004be5, 
+0x8021, 0x34028000, 0xa7a20010, 0x27b10010, 0xc004bbf, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 
+0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0xc004bbf, 0x2021, 
+0x108042, 0x1600fffc, 0x0, 0xc004bbf, 0x24040001, 0xc004bbf, 
 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, 
-0x0, 0x8f830054, 0x8004b0a, 0x24020008, 0x8f830054, 0x3c020001, 
-0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440020f, 0x24020009, 
-0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 
-0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 
-0x32020018, 0xc004b65, 0x34108000, 0xc004b65, 0x0, 0xc004b1f, 
-0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 
-0x108042, 0x1600fff7, 0x0, 0xc004b65, 0x8021, 0x97a20010, 
-0x27b10010, 0x34420001, 0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 
-0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020018, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 
-0x0, 0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x2402000a, 
-0x8f830054, 0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 
-0x1440019b, 0x2402000b, 0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 
-0x8021, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x2021, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 
-0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fffa, 0x32020017, 0xc004b65, 0x34108000, 0xc004b65, 
-0x0, 0xc004b1f, 0x0, 0x50400005, 0x108042, 0x96220000, 
-0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004b65, 
-0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, 0xc004b3f, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, 
+0x0, 0x8004b98, 0x24020002, 0x27b10010, 0xa7a00010, 0x8021, 
+0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x24040001, 
+0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0xc004bbf, 0x2021, 0x108042, 0x1600fffc, 0x0, 0xc004be5, 
+0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, 
+0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
+0x0, 0xc004be5, 0x0, 0x97a20010, 0x30428000, 0x144002dc, 
+0x24020003, 0x8004b98, 0x0, 0x24021200, 0xa7a20010, 0x27b10010, 
+0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 
+0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0xc004bbf, 0x2021, 0x108042, 0x1600fffc, 0x0, 
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 
+0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 
+0x24020004, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 0x8c6350ac, 0x10620297, 
+0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004, 
+0x10620291, 0x2402000f, 0x8004b98, 0x24020011, 0x8004b98, 0x24020005, 
+0x24020014, 0xa7a20010, 0x27b10010, 0x8021, 0xc004bbf, 0x24040001, 
+0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 
+0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, 0x10400002, 
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020012, 
+0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 
+0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 
+0x24020006, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x14400250, 0x24020007, 0x8004b98, 0x0, 0x24020006, 
+0xa7a20010, 0x27b10010, 0x8021, 0xc004bbf, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, 
+0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020013, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024, 
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 
+0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 0x24020008, 
+0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, 
+0x1440020f, 0x24020009, 0x8004b98, 0x0, 0x27b10010, 0xa7a00010, 
+0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fffa, 0x32020018, 0xc004be5, 0x34108000, 0xc004be5, 
+0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000, 
+0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004be5, 
+0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, 0xc004bbf, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 
+0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 
 0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 
-0x32020017, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, 
-0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8f830054, 
-0x8004b0a, 0x2402000c, 0x8f830054, 0x3c020001, 0x8c424e98, 0x2463ff9c, 
-0x431023, 0x2c420064, 0x14400127, 0x24020012, 0x8004b18, 0x0, 
-0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x24100010, 
-0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020014, 0xc004b65, 
-0x34108000, 0xc004b65, 0x0, 0xc004b1f, 0x0, 0x50400005, 
+0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 
+0x32020018, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 
+0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 
+0x8004b8a, 0x2402000a, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 
+0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x8004b98, 0x0, 
+0x27b10010, 0xa7a00010, 0x8021, 0xc004bbf, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x24100010, 
+0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020017, 0xc004be5, 
+0x34108000, 0xc004be5, 0x0, 0xc004b9f, 0x0, 0x50400005, 
 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 
-0x0, 0xc004b65, 0x8021, 0x97a20010, 0x27b10010, 0x34420010, 
-0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
-0x0, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 
-0x2021, 0xc004b3f, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 
-0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fffa, 0x32020014, 0xc004b3f, 0x24040001, 0xc004b3f, 
+0x0, 0xc004be5, 0x8021, 0x97a20010, 0x27b10010, 0x34420700, 
+0xa7a20010, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 
+0x2021, 0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fffa, 0x32020017, 0xc004bbf, 0x24040001, 0xc004bbf, 
 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, 
-0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 0x0, 0xc004b65, 
-0x0, 0x8f830054, 0x8004b0a, 0x24020013, 0x8f830054, 0x3c020001, 
-0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x144000b3, 0x2402000d, 
-0x8004b18, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004b3f, 
-0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 
-0x2021, 0xc004b3f, 0x24040001, 0xc004b3f, 0x24040001, 0xc004b3f, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, 
+0x0, 0x8f830054, 0x8004b8a, 0x2402000c, 0x8f830054, 0x3c020001, 
+0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012, 
+0x8004b98, 0x0, 0x27b10010, 0xa7a00010, 0x8021, 0xc004bbf, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 
+0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x24040001, 0xc004bbf, 
 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 
-0xc004b3f, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 
-0x32020018, 0xc004b65, 0x34108000, 0xc004b65, 0x0, 0xc004b1f, 
+0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 
+0x32020014, 0xc004be5, 0x34108000, 0xc004be5, 0x0, 0xc004b9f, 
 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 
-0x108042, 0x1600fff7, 0x0, 0xc004b65, 0x8021, 0x97a20010, 
-0x27b10010, 0x3042fffe, 0xa7a20010, 0xc004b3f, 0x24040001, 0x26100001, 
-0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 0x24100010, 
-0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 
-0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 
-0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020018, 0xc004b3f, 
-0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 0x501024, 
-0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fff8, 
-0x0, 0xc004b65, 0x0, 0x8f830054, 0x8004b0a, 0x2402000e, 
-0x24020840, 0xa7a20010, 0x27b10010, 0x8021, 0xc004b3f, 0x24040001, 
-0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004b3f, 0x2021, 
-0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0xc004b3f, 0x24040001, 
-0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 
-0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 
-0x2021, 0x24040001, 0xc004b3f, 0x108042, 0x1600fffa, 0x32020013, 
-0xc004b3f, 0x24040001, 0xc004b3f, 0x2021, 0x34108000, 0x96220000, 
-0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004b3f, 0x108042, 
-0x1600fff8, 0x0, 0xc004b65, 0x0, 0x8f830054, 0x24020010, 
-0x3c010001, 0xac224e10, 0x3c010001, 0x8004b1a, 0xac234e98, 0x8f830054, 
-0x3c020001, 0x8c424e98, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 
-0x0, 0x24020011, 0x3c010001, 0xac224e10, 0x8fbf0020, 0x8fb1001c, 
-0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, 
-0x431025, 0x3c030008, 0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, 
-0x8004b2b, 0x24840001, 0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 
-0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 
-0x8f830054, 0x8f820054, 0x8004b39, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0xa01021, 0x8f830044, 
-0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 0x3c020002, 0x822025, 
-0x641825, 0xaf830044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 
-0x8f830054, 0x8f820054, 0x8004b51, 0x24630001, 0x8f820054, 0x621023, 
+0x108042, 0x1600fff7, 0x0, 0xc004be5, 0x8021, 0x97a20010, 
+0x27b10010, 0x34420010, 0xa7a20010, 0xc004bbf, 0x24040001, 0x26100001, 
+0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 0x2021, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0x24100010, 
+0x32020001, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020014, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x2021, 0x34108000, 0x96220000, 0x501024, 
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fff8, 
+0x0, 0xc004be5, 0x0, 0x8f830054, 0x8004b8a, 0x24020013, 
+0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 0x2c420064, 
+0x144000b3, 0x2402000d, 0x8004b98, 0x0, 0x27b10010, 0xa7a00010, 
+0x8021, 0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 
+0x0, 0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 
+0x24040001, 0xc004bbf, 0x2021, 0x24100010, 0x32020001, 0x10400002, 
+0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 
+0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fffa, 0x32020018, 0xc004be5, 0x34108000, 0xc004be5, 
+0x0, 0xc004b9f, 0x0, 0x50400005, 0x108042, 0x96220000, 
+0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, 0xc004be5, 
+0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, 0xc004bbf, 
+0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 0xc004bbf, 
+0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0xc004bbf, 
+0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, 
+0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 
+0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 
+0x32020018, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 0x34108000, 
+0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 
+0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 0x8f830054, 
+0x8004b8a, 0x2402000e, 0x24020840, 0xa7a20010, 0x27b10010, 0x8021, 
+0xc004bbf, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, 
+0xc004bbf, 0x2021, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 
+0xc004bbf, 0x24040001, 0x24100010, 0x32020001, 0x10400002, 0x2021, 
+0x24040001, 0xc004bbf, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 
+0x32020013, 0x10400002, 0x2021, 0x24040001, 0xc004bbf, 0x108042, 
+0x1600fffa, 0x32020013, 0xc004bbf, 0x24040001, 0xc004bbf, 0x2021, 
+0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, 0x24040001, 
+0xc004bbf, 0x108042, 0x1600fff8, 0x0, 0xc004be5, 0x0, 
+0x8f830054, 0x24020010, 0x3c010001, 0xac225020, 0x3c010001, 0x8004b9a, 
+0xac2350a8, 0x8f830054, 0x3c020001, 0x8c4250a8, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, 0xac225020, 
+0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, 0x8f840054, 
+0x8f820054, 0xa32824, 0x8004bab, 0x24840001, 0x8f820054, 0x821023, 
 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 
-0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004b5f, 0x24630001, 
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004bb9, 0x24630001, 
 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 
-0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, 
-0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 
-0x8004b73, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 
-0x8f830054, 0x8f820054, 0x8004b81, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x0, 
-0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, 0x8c63839c, 0x24020008, 
-0x1462021c, 0x803021, 0x3c020001, 0x8c424e88, 0x14400033, 0x0, 
-0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001, 0x621825, 
-0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, 0x2c420001, 0x621825, 
-0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001, 0x621825, 
-0x10600005, 0x0, 0xc0041e7, 0x0, 0x8004bc1, 0x2402000e, 
-0xc004323, 0x0, 0x3c050001, 0x8ca54dec, 0xc004f33, 0x24040001, 
-0x3c030001, 0x8c634dec, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 
-0x8c424de8, 0x8004bbd, 0x2403fff7, 0x3c020001, 0x8c424de8, 0x431024, 
-0x3c010001, 0xac224de8, 0x2402000e, 0x3c010001, 0xc0041e7, 0xac226eb0, 
-0x8004dab, 0x0, 0x8f820220, 0x3c030400, 0x431024, 0x10400027, 
-0x2403ffbf, 0x8f850224, 0x3c020001, 0x8c426ebc, 0xa32024, 0x431024, 
-0x1482000c, 0x0, 0x3c020001, 0x8c426ec0, 0x24420001, 0x3c010001, 
-0xac226ec0, 0x2c420002, 0x14400008, 0x24020001, 0x3c010001, 0x8004be1, 
-0xac226ee0, 0x3c010001, 0xac206ec0, 0x3c010001, 0xac206ee0, 0x3c020001, 
-0x8c426ee0, 0x10400006, 0x30a20040, 0x10400004, 0x24020001, 0x3c010001, 
-0x8004bec, 0xac226ee4, 0x3c010001, 0xac206ee4, 0x3c010001, 0xac256ebc, 
-0x3c010001, 0x8004bfc, 0xac206ef0, 0x24020001, 0x3c010001, 0xac226ef0, 
-0x3c010001, 0xac206ee0, 0x3c010001, 0xac206ec0, 0x3c010001, 0xac206ee4, 
-0x3c010001, 0xac206ebc, 0x3c030001, 0x8c636eb0, 0x3c020001, 0x8c426eb4, 
-0x10620003, 0x3c020200, 0x3c010001, 0xac236eb4, 0xc21024, 0x10400007, 
-0x2463ffff, 0x8f820220, 0x24030001, 0x3c010001, 0xac234df0, 0x8004da9, 
-0x3c03f700, 0x2c62000e, 0x10400198, 0x31080, 0x3c010001, 0x220821, 
-0x8c224cc0, 0x400008, 0x0, 0x8ee20000, 0x3c03fdff, 0x3463ffff, 
-0x431024, 0xaee20000, 0x3c010001, 0xac206ee0, 0x3c010001, 0xac206ec0, 
-0x3c010001, 0xac206ef0, 0x3c010001, 0xac206ebc, 0x3c010001, 0xac206ee4, 
-0x3c010001, 0xac206ed8, 0x3c010001, 0xac206ed0, 0xc00470a, 0xaf800224, 
-0x24020002, 0x3c010001, 0xac226eb0, 0xc0041e7, 0x0, 0xaf800204, 
-0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, 0xac206f00, 
-0x8f830054, 0x3c020001, 0x8c426ed8, 0x24040001, 0x3c010001, 0xac246eec, 
-0x24420001, 0x3c010001, 0xac226ed8, 0x2c420004, 0x3c010001, 0xac236ed4, 
-0x14400006, 0x24020003, 0x3c010001, 0xac244df0, 0x3c010001, 0x8004da7, 
-0xac206ed8, 0x3c010001, 0x8004da7, 0xac226eb0, 0x8f830054, 0x3c020001, 
-0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400154, 0x24020004, 
-0x3c010001, 0x8004da7, 0xac226eb0, 0x3c040001, 0x8c844e8c, 0x3c010001, 
-0xc004dae, 0xac206ec8, 0x3c020001, 0x8c426efc, 0xaf820204, 0x8f820204, 
-0x30420030, 0x1440013c, 0x24020002, 0x3c030001, 0x8c636efc, 0x24020005, 
-0x3c010001, 0xac226eb0, 0x3c010001, 0x8004da7, 0xac236f00, 0x3c020001, 
-0x8c426ee0, 0x10400139, 0x0, 0x3c020001, 0x8c426ebc, 0x10400135, 
-0x0, 0x3c010001, 0xac226ee8, 0x24020003, 0x3c010001, 0xac226ec0, 
-0x8004d3a, 0x24020006, 0x3c010001, 0xac206ec8, 0x8f820204, 0x34420040, 
-0xaf820204, 0x3c020001, 0x8c426f00, 0x24030007, 0x3c010001, 0xac236eb0, 
-0x34420040, 0x3c010001, 0xac226f00, 0x3c020001, 0x8c426ee0, 0x10400005, 
-0x0, 0x3c020001, 0x8c426ebc, 0x10400110, 0x24020002, 0x3c050001, 
-0x24a56ec0, 0x8ca20000, 0x2c424e21, 0x1040010a, 0x24020002, 0x3c020001, 
-0x8c426ee4, 0x1040010f, 0x2404ffbf, 0x3c020001, 0x8c426ebc, 0x3c030001, 
-0x8c636ee8, 0x441024, 0x641824, 0x14430007, 0x24020001, 0x24020003, 
-0xaca20000, 0x24020008, 0x3c010001, 0x8004da7, 0xac226eb0, 0x3c010001, 
-0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426eec, 0x1040000c, 0x24020001, 
-0x3c040001, 0xc004dbb, 0x8c846ebc, 0x3c020001, 0x8c426f08, 0x14400005, 
-0x24020001, 0x3c020001, 0x8c426f04, 0x10400006, 0x24020001, 0x3c010001, 
-0xac224df0, 0x3c010001, 0x8004da7, 0xac206ed8, 0x8f820204, 0x34420040, 
-0xaf820204, 0x3c020001, 0x8c426f00, 0x3c030001, 0x8c636ed0, 0x34420040, 
-0x3c010001, 0xac226f00, 0x3c020001, 0x8c426ebc, 0x2c630001, 0x318c0, 
-0x3c010001, 0xac236ed0, 0x30420008, 0x3c010001, 0xac226ecc, 0x8f830054, 
-0x24020009, 0x3c010001, 0xac226eb0, 0x3c010001, 0x8004da7, 0xac236ed4, 
-0x8f830054, 0x3c020001, 0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 
-0x144000b6, 0x0, 0x3c020001, 0x8c426ee0, 0x10400005, 0x0, 
-0x3c020001, 0x8c426ebc, 0x104000b7, 0x24020002, 0x3c030001, 0x24636ec0, 
-0x8c620000, 0x2c424e21, 0x104000b1, 0x24020002, 0x3c020001, 0x8c426eec, 
-0x1040000e, 0x0, 0x3c020001, 0x8c426ebc, 0x3c010001, 0xac206eec, 
-0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, 0x1440000c, 
-0x24020003, 0x8004d27, 0x2402000c, 0x3c020001, 0x8c426ebc, 0x30420080, 
-0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003, 
-0xac620000, 0x2402000a, 0x3c010001, 0xac226eb0, 0x3c040001, 0x24846ef8, 
-0x8c820000, 0x3c030001, 0x8c636ed0, 0x431025, 0xaf820204, 0x8c830000, 
-0x3c040001, 0x8c846ed0, 0x2402000b, 0x3c010001, 0xac226eb0, 0x641825, 
-0x3c010001, 0xac236f00, 0x3c050001, 0x24a56ec0, 0x8ca20000, 0x2c424e21, 
-0x1040007d, 0x24020002, 0x3c020001, 0x8c426ef0, 0x10400005, 0x0, 
-0x2402000c, 0x3c010001, 0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426ee0, 
-0x1040007a, 0x0, 0x3c040001, 0x8c846ebc, 0x1080006c, 0x30820008, 
-0x3c030001, 0x8c636ecc, 0x10620072, 0x24020003, 0x3c010001, 0xac246ee8, 
-0xaca20000, 0x24020006, 0x3c010001, 0x8004da7, 0xac226eb0, 0x8f8400f0, 
-0x276217f8, 0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, 0x10a20007, 
-0x3c038000, 0x34630040, 0x3c020001, 0x24424d90, 0xac820000, 0xac830004, 
-0xaf8500f0, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, 
-0x3c010001, 0xac226eb0, 0x3c010001, 0xac236ed4, 0x8f830054, 0x3c020001, 
-0x8c426ed4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440003a, 0x0, 
-0x3c020001, 0x8c426ef0, 0x10400029, 0x2402000e, 0x3c030001, 0x8c636f04, 
-0x3c010001, 0x14600015, 0xac226eb0, 0xc004323, 0x0, 0x3c050001, 
-0x8ca54dec, 0xc004f33, 0x24040001, 0x3c030001, 0x8c634dec, 0x24020004, 
-0x14620005, 0x2403fffb, 0x3c020001, 0x8c424de8, 0x8004d76, 0x2403fff7, 
-0x3c020001, 0x8c424de8, 0x431024, 0x3c010001, 0xac224de8, 0x8ee20000, 
-0x3c030200, 0x431025, 0xaee20000, 0x8f820224, 0x3c010001, 0xac226f0c, 
-0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, 0x34420002, 
-0x8004da7, 0xaf820220, 0x3c020001, 0x8c426ee0, 0x10400005, 0x0, 
-0x3c020001, 0x8c426ebc, 0x1040000f, 0x24020002, 0x3c020001, 0x8c426ec0, 
-0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, 0x8c426ee0, 0x1040000f, 
-0x0, 0x3c020001, 0x8c426ebc, 0x1440000b, 0x0, 0x24020002, 
-0x3c010001, 0x8004da7, 0xac226eb0, 0x3c020001, 0x8c426ee0, 0x10400003, 
-0x0, 0xc0041e7, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 
-0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030001, 0x24636f08, 
-0x8c620000, 0x10400005, 0x34422000, 0x3c010001, 0xac226efc, 0x8004db9, 
-0xac600000, 0x3c010001, 0xac246efc, 0x3e00008, 0x0, 0x27bdffe0, 
-0x30820030, 0xafbf0018, 0x3c010001, 0xac226f04, 0x14400067, 0x3c02ffff, 
-0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d, 
-0x30838000, 0x31a02, 0x30820001, 0x21200, 0x3c040001, 0x8c844e8c, 
-0x621825, 0x331c2, 0x3c030001, 0x24634e6c, 0x30828000, 0x21202, 
-0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021, 
-0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, 0x10600007, 
-0x24020002, 0x10620013, 0x24020003, 0x1062002c, 0x3c05000f, 0x8004e1d, 
-0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x3c010001, 0xac206f44, 
-0x3c010001, 0x8004e28, 0xac206f4c, 0x8f820200, 0x34420100, 0xaf820200, 
-0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x24020100, 
-0x3c010001, 0xac226f44, 0x3c010001, 0x8004e28, 0xac206f4c, 0x8f820200, 
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 
-0xaf820220, 0x3c010001, 0xac206f44, 0x3c010001, 0x8004e28, 0xac236f4c, 
-0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 
-0xaf820220, 0x24020100, 0x3c010001, 0xac226f44, 0x3c010001, 0x8004e28, 
-0xac236f4c, 0x34a5ffff, 0x3c040001, 0x24844cf8, 0xafa30010, 0xc0023a7, 
-0xafa00014, 0x8004e28, 0x0, 0x24020030, 0x3c010001, 0xac226f08, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8, 0xafb10024, 
-0x808821, 0xafb3002c, 0xa09821, 0xafb00020, 0xc08021, 0x3c040001, 
-0x24844d10, 0x3c050009, 0x3c020001, 0x8c424dec, 0x34a59001, 0x2203021, 
-0x2603821, 0xafbf0030, 0xafb20028, 0xa7a0001a, 0xafb00014, 0xc0023a7, 
-0xafa20010, 0x24020002, 0x126200e9, 0x2e620003, 0x10400005, 0x24020001, 
-0x1262000a, 0x3c02fffb, 0x8004f2c, 0x0, 0x24020004, 0x1262006d, 
-0x24020008, 0x1262006c, 0x3c02ffec, 0x8004f2c, 0x0, 0x3442ffff, 
-0x2028024, 0x119140, 0x3c010001, 0x320821, 0xac306f1c, 0x3c024000, 
-0x2021024, 0x10400046, 0x1023c2, 0x30840030, 0x101382, 0x3042000c, 
-0x3c030001, 0x24634e14, 0x431021, 0x823821, 0x3c020020, 0x2021024, 
-0x10400006, 0x24020100, 0x3c010001, 0x320821, 0xac226f20, 0x8004e6f, 
-0x3c020080, 0x3c010001, 0x320821, 0xac206f20, 0x3c020080, 0x2021024, 
-0x10400006, 0x111940, 0x3c020001, 0x3c010001, 0x230821, 0x8004e7b, 
-0xac226f28, 0x111140, 0x3c010001, 0x220821, 0xac206f28, 0x94e30000, 
-0x32024000, 0x10400003, 0xa7a30018, 0x34624000, 0xa7a20018, 0x24040001, 
-0x94e20002, 0x24050004, 0x24e60002, 0x34420001, 0xc004782, 0xa4e20002, 
-0x24040001, 0x2821, 0xc004782, 0x27a60018, 0x3c020001, 0x8c424dec, 
-0x24110001, 0x3c010001, 0xac314df8, 0x14530004, 0x32028000, 0xc0041e7, 
-0x0, 0x32028000, 0x10400095, 0x0, 0xc0041e7, 0x0, 
-0x24020002, 0x3c010001, 0xac314df0, 0x3c010001, 0x8004f2c, 0xac224dec, 
-0x24040001, 0x24050004, 0x27b0001a, 0xc004782, 0x2003021, 0x24040001, 
-0x2821, 0xc004782, 0x2003021, 0x3c020001, 0x521021, 0x8c426f14, 
-0x3c040001, 0x8c844dec, 0x3c03bfff, 0x3463ffff, 0x3c010001, 0xac334df8, 
-0x431024, 0x3c010001, 0x320821, 0x10930074, 0xac226f14, 0x8004f2c, 
-0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, 
-0x111140, 0x3c010001, 0x220821, 0xac306f18, 0x3c022000, 0x2021024, 
-0x10400005, 0x24020001, 0x3c010001, 0xac224e88, 0x8004ecd, 0x3c024000, 
-0x3c010001, 0xac204e88, 0x3c024000, 0x2021024, 0x1440001c, 0x0, 
-0x3c020001, 0x8c424e88, 0x10400007, 0x24022020, 0x3c010001, 0xac224e8c, 
-0x24020001, 0x3c010001, 0x370821, 0xac22839c, 0x3c04bfff, 0x111940, 
-0x3c020001, 0x431021, 0x8c426f10, 0x3c050001, 0x8ca54dec, 0x3484ffff, 
-0x441024, 0x3c010001, 0x230821, 0xac226f10, 0x24020001, 0x10a20044, 
-0x0, 0x8004f2a, 0x0, 0x3c020001, 0x8c424e88, 0x1040001c, 
-0x24022000, 0x3c010001, 0xac224e8c, 0x3c0300a0, 0x2031024, 0x14430005, 
-0x111140, 0x3402a000, 0x3c010001, 0x8004f25, 0xac224e8c, 0x3c030001, 
-0x621821, 0x8c636f18, 0x3c020020, 0x621024, 0x10400004, 0x24022001, 
-0x3c010001, 0x8004f25, 0xac224e8c, 0x3c020080, 0x621024, 0x1040001f, 
-0x3402a001, 0x3c010001, 0x8004f25, 0xac224e8c, 0x3c020020, 0x2021024, 
-0x10400007, 0x111940, 0x24020100, 0x3c010001, 0x230821, 0xac226f24, 
-0x8004f19, 0x3c020080, 0x111140, 0x3c010001, 0x220821, 0xac206f24, 
+0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 
+0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c030001, 
+0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004bd1, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 
+0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 
+0x8004bdf, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
+0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 
+0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 
+0x8f830054, 0x8f820054, 0x8004bf3, 0x24630001, 0x8f820054, 0x621023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x8004c01, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 
+0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, 
+0x8c63839c, 0x24020008, 0x1462021c, 0x803021, 0x3c020001, 0x8c425098, 
+0x14400033, 0x0, 0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, 
+0x2c420001, 0x621825, 0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, 
+0x2c420001, 0x621825, 0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, 
+0x2c420001, 0x621825, 0x10600005, 0x0, 0xc00428b, 0x0, 
+0x8004c41, 0x2402000e, 0xc0043cd, 0x0, 0x3c050001, 0x8ca54ffc, 
+0xc004fb3, 0x24040001, 0x3c030001, 0x8c634ffc, 0x24020004, 0x14620005, 
+0x2403fffb, 0x3c020001, 0x8c424ff8, 0x8004c3d, 0x2403fff7, 0x3c020001, 
+0x8c424ff8, 0x431024, 0x3c010001, 0xac224ff8, 0x2402000e, 0x3c010001, 
+0xc00428b, 0xac2270c0, 0x8004e2b, 0x0, 0x8f820220, 0x3c030400, 
+0x431024, 0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001, 0x8c4270cc, 
+0xa32024, 0x431024, 0x1482000c, 0x0, 0x3c020001, 0x8c4270d0, 
+0x24420001, 0x3c010001, 0xac2270d0, 0x2c420002, 0x14400008, 0x24020001, 
+0x3c010001, 0x8004c61, 0xac2270f0, 0x3c010001, 0xac2070d0, 0x3c010001, 
+0xac2070f0, 0x3c020001, 0x8c4270f0, 0x10400006, 0x30a20040, 0x10400004, 
+0x24020001, 0x3c010001, 0x8004c6c, 0xac2270f4, 0x3c010001, 0xac2070f4, 
+0x3c010001, 0xac2570cc, 0x3c010001, 0x8004c7c, 0xac207100, 0x24020001, 
+0x3c010001, 0xac227100, 0x3c010001, 0xac2070f0, 0x3c010001, 0xac2070d0, 
+0x3c010001, 0xac2070f4, 0x3c010001, 0xac2070cc, 0x3c030001, 0x8c6370c0, 
+0x3c020001, 0x8c4270c4, 0x10620003, 0x3c020200, 0x3c010001, 0xac2370c4, 
+0xc21024, 0x10400007, 0x2463ffff, 0x8f820220, 0x24030001, 0x3c010001, 
+0xac235000, 0x8004e29, 0x3c03f700, 0x2c62000e, 0x10400198, 0x31080, 
+0x3c010001, 0x220821, 0x8c224ed0, 0x400008, 0x0, 0x8ee20000, 
+0x3c03fdff, 0x3463ffff, 0x431024, 0xaee20000, 0x3c010001, 0xac2070f0, 
+0x3c010001, 0xac2070d0, 0x3c010001, 0xac207100, 0x3c010001, 0xac2070cc, 
+0x3c010001, 0xac2070f4, 0x3c010001, 0xac2070e8, 0x3c010001, 0xac2070e0, 
+0xc00478a, 0xaf800224, 0x24020002, 0x3c010001, 0xac2270c0, 0xc00428b, 
+0x0, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 
+0x3c010001, 0xac207110, 0x8f830054, 0x3c020001, 0x8c4270e8, 0x24040001, 
+0x3c010001, 0xac2470fc, 0x24420001, 0x3c010001, 0xac2270e8, 0x2c420004, 
+0x3c010001, 0xac2370e4, 0x14400006, 0x24020003, 0x3c010001, 0xac245000, 
+0x3c010001, 0x8004e27, 0xac2070e8, 0x3c010001, 0x8004e27, 0xac2270c0, 
+0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 0x431023, 0x2c422710, 
+0x14400154, 0x24020004, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c040001, 
+0x8c84509c, 0x3c010001, 0xc004e2e, 0xac2070d8, 0x3c020001, 0x8c42710c, 
+0xaf820204, 0x8f820204, 0x30420030, 0x1440013c, 0x24020002, 0x3c030001, 
+0x8c63710c, 0x24020005, 0x3c010001, 0xac2270c0, 0x3c010001, 0x8004e27, 
+0xac237110, 0x3c020001, 0x8c4270f0, 0x10400139, 0x0, 0x3c020001, 
+0x8c4270cc, 0x10400135, 0x0, 0x3c010001, 0xac2270f8, 0x24020003, 
+0x3c010001, 0xac2270d0, 0x8004dba, 0x24020006, 0x3c010001, 0xac2070d8, 
+0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c427110, 0x24030007, 
+0x3c010001, 0xac2370c0, 0x34420040, 0x3c010001, 0xac227110, 0x3c020001, 
+0x8c4270f0, 0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x10400110, 
+0x24020002, 0x3c050001, 0x24a570d0, 0x8ca20000, 0x2c424e21, 0x1040010a, 
+0x24020002, 0x3c020001, 0x8c4270f4, 0x1040010f, 0x2404ffbf, 0x3c020001, 
+0x8c4270cc, 0x3c030001, 0x8c6370f8, 0x441024, 0x641824, 0x14430007, 
+0x24020001, 0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 0x8004e27, 
+0xac2270c0, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c020001, 0x8c4270fc, 
+0x1040000c, 0x24020001, 0x3c040001, 0xc004e3b, 0x8c8470cc, 0x3c020001, 
+0x8c427118, 0x14400005, 0x24020001, 0x3c020001, 0x8c427114, 0x10400006, 
+0x24020001, 0x3c010001, 0xac225000, 0x3c010001, 0x8004e27, 0xac2070e8, 
+0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c427110, 0x3c030001, 
+0x8c6370e0, 0x34420040, 0x3c010001, 0xac227110, 0x3c020001, 0x8c4270cc, 
+0x2c630001, 0x318c0, 0x3c010001, 0xac2370e0, 0x30420008, 0x3c010001, 
+0xac2270dc, 0x8f830054, 0x24020009, 0x3c010001, 0xac2270c0, 0x3c010001, 
+0x8004e27, 0xac2370e4, 0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 
+0x431023, 0x2c422710, 0x144000b6, 0x0, 0x3c020001, 0x8c4270f0, 
+0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x104000b7, 0x24020002, 
+0x3c030001, 0x246370d0, 0x8c620000, 0x2c424e21, 0x104000b1, 0x24020002, 
+0x3c020001, 0x8c4270fc, 0x1040000e, 0x0, 0x3c020001, 0x8c4270cc, 
+0x3c010001, 0xac2070fc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 
+0x30420080, 0x1440000c, 0x24020003, 0x8004da7, 0x2402000c, 0x3c020001, 
+0x8c4270cc, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 
+0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 0xac2270c0, 
+0x3c040001, 0x24847108, 0x8c820000, 0x3c030001, 0x8c6370e0, 0x431025, 
+0xaf820204, 0x8c830000, 0x3c040001, 0x8c8470e0, 0x2402000b, 0x3c010001, 
+0xac2270c0, 0x641825, 0x3c010001, 0xac237110, 0x3c050001, 0x24a570d0, 
+0x8ca20000, 0x2c424e21, 0x1040007d, 0x24020002, 0x3c020001, 0x8c427100, 
+0x10400005, 0x0, 0x2402000c, 0x3c010001, 0x8004e27, 0xac2270c0, 
+0x3c020001, 0x8c4270f0, 0x1040007a, 0x0, 0x3c040001, 0x8c8470cc, 
+0x1080006c, 0x30820008, 0x3c030001, 0x8c6370dc, 0x10620072, 0x24020003, 
+0x3c010001, 0xac2470f8, 0xaca20000, 0x24020006, 0x3c010001, 0x8004e27, 
+0xac2270c0, 0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, 0x27651000, 
+0x8f8200f4, 0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, 0x24424fa0, 
+0xac820000, 0xac830004, 0xaf8500f0, 0x8f820200, 0x34420002, 0xaf820200, 
+0x8f830054, 0x2402000d, 0x3c010001, 0xac2270c0, 0x3c010001, 0xac2370e4, 
+0x8f830054, 0x3c020001, 0x8c4270e4, 0x2463d8f0, 0x431023, 0x2c422710, 
+0x1440003a, 0x0, 0x3c020001, 0x8c427100, 0x10400029, 0x2402000e, 
+0x3c030001, 0x8c637114, 0x3c010001, 0x14600015, 0xac2270c0, 0xc0043cd, 
+0x0, 0x3c050001, 0x8ca54ffc, 0xc004fb3, 0x24040001, 0x3c030001, 
+0x8c634ffc, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 0x8c424ff8, 
+0x8004df6, 0x2403fff7, 0x3c020001, 0x8c424ff8, 0x431024, 0x3c010001, 
+0xac224ff8, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, 0x8f820224, 
+0x3c010001, 0xac22711c, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 
+0x8f820220, 0x34420002, 0x8004e27, 0xaf820220, 0x3c020001, 0x8c4270f0, 
+0x10400005, 0x0, 0x3c020001, 0x8c4270cc, 0x1040000f, 0x24020002, 
+0x3c020001, 0x8c4270d0, 0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, 
+0x8c4270f0, 0x1040000f, 0x0, 0x3c020001, 0x8c4270cc, 0x1440000b, 
+0x0, 0x24020002, 0x3c010001, 0x8004e27, 0xac2270c0, 0x3c020001, 
+0x8c4270f0, 0x10400003, 0x0, 0xc00428b, 0x0, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
+0x3c030001, 0x24637118, 0x8c620000, 0x10400005, 0x34422000, 0x3c010001, 
+0xac22710c, 0x8004e39, 0xac600000, 0x3c010001, 0xac24710c, 0x3e00008, 
+0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001, 0xac227114, 
+0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, 
+0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200, 
+0x3c040001, 0x8c84509c, 0x621825, 0x331c2, 0x3c030001, 0x2463507c, 
+0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, 
+0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, 
+0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c, 
+0x3c05000f, 0x8004e9d, 0x0, 0x8f820200, 0x2403feff, 0x431024, 
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 
+0x3c010001, 0xac207154, 0x3c010001, 0x8004ea8, 0xac20715c, 0x8f820200, 
+0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 
+0xaf820220, 0x24020100, 0x3c010001, 0xac227154, 0x3c010001, 0x8004ea8, 
+0xac20715c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
+0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 0xac207154, 0x3c010001, 
+0x8004ea8, 0xac23715c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 
+0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, 0xac227154, 
+0x3c010001, 0x8004ea8, 0xac23715c, 0x34a5ffff, 0x3c040001, 0x24844f08, 
+0xafa30010, 0xc002403, 0xafa00014, 0x8004ea8, 0x0, 0x24020030, 
+0x3c010001, 0xac227118, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x27bdffc8, 0xafb10024, 0x808821, 0xafb3002c, 0xa09821, 0xafb00020, 
+0xc08021, 0x3c040001, 0x24844f20, 0x3c050009, 0x3c020001, 0x8c424ffc, 
+0x34a59001, 0x2203021, 0x2603821, 0xafbf0030, 0xafb20028, 0xa7a0001a, 
+0xafb00014, 0xc002403, 0xafa20010, 0x24020002, 0x126200e9, 0x2e620003, 
+0x10400005, 0x24020001, 0x1262000a, 0x3c02fffb, 0x8004fac, 0x0, 
+0x24020004, 0x1262006d, 0x24020008, 0x1262006c, 0x3c02ffec, 0x8004fac, 
+0x0, 0x3442ffff, 0x2028024, 0x119140, 0x3c010001, 0x320821, 
+0xac30712c, 0x3c024000, 0x2021024, 0x10400046, 0x1023c2, 0x30840030, 
+0x101382, 0x3042000c, 0x3c030001, 0x24635024, 0x431021, 0x823821, 
+0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, 0x320821, 
+0xac227130, 0x8004eef, 0x3c020080, 0x3c010001, 0x320821, 0xac207130, 
 0x3c020080, 0x2021024, 0x10400006, 0x111940, 0x3c020001, 0x3c010001, 
-0x230821, 0x8004f25, 0xac226f2c, 0x111140, 0x3c010001, 0x220821, 
-0xac206f2c, 0x3c030001, 0x8c634dec, 0x24020001, 0x10620003, 0x0, 
-0xc0041e7, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 
-0x8fb00020, 0x3e00008, 0x27bd0038, 0x27bdffd0, 0xafb40028, 0x80a021, 
-0xafb20020, 0x9021, 0xafb30024, 0x9821, 0xafb1001c, 0x8821, 
-0x24020002, 0xafbf002c, 0xafb00018, 0xa7a00012, 0x10a20068, 0xa7a00010, 
-0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 0x148140, 0x8004ff0, 
-0x2201021, 0x24020004, 0x10a2005e, 0x24020008, 0x10a2005d, 0x142140, 
-0x8004ff0, 0x2201021, 0x3c030001, 0x701821, 0x8c636f1c, 0x3c024000, 
-0x621024, 0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 0x628824, 
-0x3c010001, 0x300821, 0xac316f14, 0x8004ff0, 0x2201021, 0x24050001, 
-0xc004740, 0x27a60010, 0x24040001, 0x24050001, 0xc004740, 0x27a60010, 
-0x97a20010, 0x30420004, 0x10400034, 0x3c114000, 0x3c030001, 0x8c634e9c, 
-0x24020003, 0x10620008, 0x2c620004, 0x14400029, 0x3c028000, 0x24020004, 
-0x10620014, 0x24040001, 0x8004f99, 0x3c028000, 0x24040001, 0x24050011, 
-0x27b00012, 0xc004740, 0x2003021, 0x24040001, 0x24050011, 0xc004740, 
-0x2003021, 0x97a30012, 0x30624000, 0x10400002, 0x3c130010, 0x3c130008, 
-0x3c120001, 0x8004f96, 0x30628000, 0x24050014, 0x27b00012, 0xc004740, 
-0x2003021, 0x24040001, 0x24050014, 0xc004740, 0x2003021, 0x97a30012, 
-0x30621000, 0x10400002, 0x3c130010, 0x3c130008, 0x3c120001, 0x30620800, 
-0x54400001, 0x3c120002, 0x3c028000, 0x2221025, 0x2531825, 0x8004fa3, 
-0x438825, 0x3c110001, 0x2308821, 0x8e316f1c, 0x3c027fff, 0x3442ffff, 
-0x2228824, 0x141140, 0x3c010001, 0x220821, 0xac316f14, 0x8004ff0, 
-0x2201021, 0x142140, 0x3c030001, 0x641821, 0x8c636f18, 0x3c024000, 
-0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001, 
-0x240821, 0xac316f10, 0x8004ff0, 0x2201021, 0x3c020001, 0x8c424dfc, 
-0x1040002d, 0x3c11c00c, 0x3c020001, 0x8c424e88, 0x3c03e00c, 0x3c010001, 
-0x240821, 0x8c246f24, 0x2102b, 0x21023, 0x431024, 0x10800004, 
-0x518825, 0x3c020020, 0x8004fcd, 0x2228825, 0x3c02ffdf, 0x3442ffff, 
-0x2228824, 0x141140, 0x3c010001, 0x220821, 0x8c226f2c, 0x10400003, 
-0x3c020080, 0x8004fd8, 0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, 
-0x3c020001, 0x8c424e60, 0x10400002, 0x3c020800, 0x2228825, 0x3c020001, 
-0x8c424e64, 0x10400002, 0x3c020400, 0x2228825, 0x3c020001, 0x8c424e68, 
-0x10400006, 0x3c020100, 0x8004feb, 0x2228825, 0x3c027fff, 0x3442ffff, 
-0x628824, 0x141140, 0x3c010001, 0x220821, 0xac316f10, 0x2201021, 
-0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 
-0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb40020, 0x80a021, 0xafbf0024, 
-0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 0x8f900200, 0x3c030001, 
-0x8c634dec, 0x8f930220, 0x24020002, 0x106200b1, 0x2c620003, 0x10400005, 
-0x24020001, 0x1062000a, 0x141940, 0x80050b7, 0x0, 0x24020004, 
-0x1062005a, 0x24020008, 0x10620059, 0x149140, 0x80050b7, 0x0, 
-0x3c040001, 0x832021, 0x8c846f1c, 0x3c110001, 0x2238821, 0x8e316f14, 
-0x3c024000, 0x821024, 0x1040003e, 0x3c020008, 0x2221024, 0x10400020, 
-0x36100002, 0x3c020001, 0x431021, 0x8c426f20, 0x10400005, 0x36100020, 
-0x36100100, 0x3c020020, 0x800502f, 0x2228825, 0x2402feff, 0x2028024, 
+0x230821, 0x8004efb, 0xac227138, 0x111140, 0x3c010001, 0x220821, 
+0xac207138, 0x94e30000, 0x32024000, 0x10400003, 0xa7a30018, 0x34624000, 
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 0x24e60002, 0x34420001, 
+0xc004802, 0xa4e20002, 0x24040001, 0x2821, 0xc004802, 0x27a60018, 
+0x3c020001, 0x8c424ffc, 0x24110001, 0x3c010001, 0xac315008, 0x14530004, 
+0x32028000, 0xc00428b, 0x0, 0x32028000, 0x10400095, 0x0, 
+0xc00428b, 0x0, 0x24020002, 0x3c010001, 0xac315000, 0x3c010001, 
+0x8004fac, 0xac224ffc, 0x24040001, 0x24050004, 0x27b0001a, 0xc004802, 
+0x2003021, 0x24040001, 0x2821, 0xc004802, 0x2003021, 0x3c020001, 
+0x521021, 0x8c427124, 0x3c040001, 0x8c844ffc, 0x3c03bfff, 0x3463ffff, 
+0x3c010001, 0xac335008, 0x431024, 0x3c010001, 0x320821, 0x10930074, 
+0xac227124, 0x8004fac, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 
+0x3c020008, 0x2028025, 0x111140, 0x3c010001, 0x220821, 0xac307128, 
+0x3c022000, 0x2021024, 0x10400005, 0x24020001, 0x3c010001, 0xac225098, 
+0x8004f4d, 0x3c024000, 0x3c010001, 0xac205098, 0x3c024000, 0x2021024, 
+0x1440001c, 0x0, 0x3c020001, 0x8c425098, 0x10400007, 0x24022020, 
+0x3c010001, 0xac22509c, 0x24020001, 0x3c010001, 0x370821, 0xac22839c, 
+0x3c04bfff, 0x111940, 0x3c020001, 0x431021, 0x8c427120, 0x3c050001, 
+0x8ca54ffc, 0x3484ffff, 0x441024, 0x3c010001, 0x230821, 0xac227120, 
+0x24020001, 0x10a20044, 0x0, 0x8004faa, 0x0, 0x3c020001, 
+0x8c425098, 0x1040001c, 0x24022000, 0x3c010001, 0xac22509c, 0x3c0300a0, 
+0x2031024, 0x14430005, 0x111140, 0x3402a000, 0x3c010001, 0x8004fa5, 
+0xac22509c, 0x3c030001, 0x621821, 0x8c637128, 0x3c020020, 0x621024, 
+0x10400004, 0x24022001, 0x3c010001, 0x8004fa5, 0xac22509c, 0x3c020080, 
+0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x8004fa5, 0xac22509c, 
+0x3c020020, 0x2021024, 0x10400007, 0x111940, 0x24020100, 0x3c010001, 
+0x230821, 0xac227134, 0x8004f99, 0x3c020080, 0x111140, 0x3c010001, 
+0x220821, 0xac207134, 0x3c020080, 0x2021024, 0x10400006, 0x111940, 
+0x3c020001, 0x3c010001, 0x230821, 0x8004fa5, 0xac22713c, 0x111140, 
+0x3c010001, 0x220821, 0xac20713c, 0x3c030001, 0x8c634ffc, 0x24020001, 
+0x10620003, 0x0, 0xc00428b, 0x0, 0x8fbf0030, 0x8fb3002c, 
+0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0038, 0x27bdffd0, 
+0xafb40028, 0x80a021, 0xafb20020, 0x9021, 0xafb30024, 0x9821, 
+0xafb1001c, 0x8821, 0x24020002, 0xafbf002c, 0xafb00018, 0xa7a00012, 
+0x10a20068, 0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 
+0x148140, 0x8005070, 0x2201021, 0x24020004, 0x10a2005e, 0x24020008, 
+0x10a2005d, 0x142140, 0x8005070, 0x2201021, 0x3c030001, 0x701821, 
+0x8c63712c, 0x3c024000, 0x621024, 0x14400009, 0x24040001, 0x3c027fff, 
+0x3442ffff, 0x628824, 0x3c010001, 0x300821, 0xac317124, 0x8005070, 
+0x2201021, 0x24050001, 0xc0047c0, 0x27a60010, 0x24040001, 0x24050001, 
+0xc0047c0, 0x27a60010, 0x97a20010, 0x30420004, 0x10400034, 0x3c114000, 
+0x3c030001, 0x8c6350ac, 0x24020003, 0x10620008, 0x2c620004, 0x14400029, 
+0x3c028000, 0x24020004, 0x10620014, 0x24040001, 0x8005019, 0x3c028000, 
+0x24040001, 0x24050011, 0x27b00012, 0xc0047c0, 0x2003021, 0x24040001, 
+0x24050011, 0xc0047c0, 0x2003021, 0x97a30012, 0x30624000, 0x10400002, 
+0x3c130010, 0x3c130008, 0x3c120001, 0x8005016, 0x30628000, 0x24050014, 
+0x27b00012, 0xc0047c0, 0x2003021, 0x24040001, 0x24050014, 0xc0047c0, 
+0x2003021, 0x97a30012, 0x30621000, 0x10400002, 0x3c130010, 0x3c130008, 
+0x3c120001, 0x30620800, 0x54400001, 0x3c120002, 0x3c028000, 0x2221025, 
+0x2531825, 0x8005023, 0x438825, 0x3c110001, 0x2308821, 0x8e31712c, 
+0x3c027fff, 0x3442ffff, 0x2228824, 0x141140, 0x3c010001, 0x220821, 
+0xac317124, 0x8005070, 0x2201021, 0x142140, 0x3c030001, 0x641821, 
+0x8c637128, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 
+0x628824, 0x3c010001, 0x240821, 0xac317120, 0x8005070, 0x2201021, 
+0x3c020001, 0x8c42500c, 0x1040002d, 0x3c11c00c, 0x3c020001, 0x8c425098, 
+0x3c03e00c, 0x3c010001, 0x240821, 0x8c247134, 0x2102b, 0x21023, 
+0x431024, 0x10800004, 0x518825, 0x3c020020, 0x800504d, 0x2228825, 
 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, 0x3c010001, 0x220821, 
-0x8c226f28, 0x10400005, 0x3c020001, 0x2629825, 0x3c020080, 0x800504e, 
-0x2228825, 0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff7f, 0x3442ffff, 
-0x800504e, 0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe, 0x3442ffff, 
-0x2629824, 0x3c02ff5f, 0x3442ffff, 0x2228824, 0x3c010001, 0x230821, 
-0xac206f20, 0x3c010001, 0x230821, 0xac206f28, 0xc00470a, 0x0, 
-0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 
-0x8f820220, 0x34420002, 0xaf820220, 0x8005065, 0x141140, 0x8f820200, 
-0x2403fffd, 0x431024, 0xc00470a, 0xaf820200, 0x3c02bfff, 0x3442ffff, 
-0xc0041e7, 0x2228824, 0x141140, 0x3c010001, 0x220821, 0x80050b7, 
-0xac316f14, 0x149140, 0x3c040001, 0x922021, 0x8c846f18, 0x3c110001, 
-0x2328821, 0x8e316f10, 0x3c024000, 0x821024, 0x14400011, 0x0, 
-0x3c020001, 0x8c424e88, 0x14400006, 0x3c02bfff, 0x8f820200, 0x34420002, 
-0xc00470a, 0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc0041e7, 0x2228824, 
-0x3c010001, 0x320821, 0x80050b7, 0xac316f10, 0x3c020001, 0x8c424e88, 
-0x1440002d, 0x141140, 0x3c020020, 0x821024, 0x10400007, 0x36100020, 
-0x24020100, 0x3c010001, 0x320821, 0xac226f24, 0x8005097, 0x36100100, 
-0x3c010001, 0x320821, 0xac206f24, 0x2402feff, 0x2028024, 0x3c020080, 
-0x821024, 0x10400007, 0x141940, 0x3c020001, 0x3c010001, 0x230821, 
-0xac226f2c, 0x80050a8, 0x2629825, 0x141140, 0x3c010001, 0x220821, 
-0xac206f2c, 0x3c02fffe, 0x3442ffff, 0x2629824, 0xc00470a, 0x0, 
-0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 
-0x8f820220, 0x34420002, 0xaf820220, 0x141140, 0x3c010001, 0x220821, 
-0xac316f10, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 
-0x8fb00010, 0x3e00008, 0x27bd0028, 0x0, 0x0 };
-u32 tigonFwData[(MAX_DATA_LEN/4) + 1] = {
+0x8c22713c, 0x10400003, 0x3c020080, 0x8005058, 0x2228825, 0x3c02ff7f, 
+0x3442ffff, 0x2228824, 0x3c020001, 0x8c425070, 0x10400002, 0x3c020800, 
+0x2228825, 0x3c020001, 0x8c425074, 0x10400002, 0x3c020400, 0x2228825, 
+0x3c020001, 0x8c425078, 0x10400006, 0x3c020100, 0x800506b, 0x2228825, 
+0x3c027fff, 0x3442ffff, 0x628824, 0x141140, 0x3c010001, 0x220821, 
+0xac317120, 0x2201021, 0x8fbf002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, 
+0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffd8, 0xafb40020, 
+0x80a021, 0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014, 0xafb00010, 
+0x8f900200, 0x3c030001, 0x8c634ffc, 0x8f930220, 0x24020002, 0x106200b1, 
+0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 0x141940, 0x8005137, 
+0x0, 0x24020004, 0x1062005a, 0x24020008, 0x10620059, 0x149140, 
+0x8005137, 0x0, 0x3c040001, 0x832021, 0x8c84712c, 0x3c110001, 
+0x2238821, 0x8e317124, 0x3c024000, 0x821024, 0x1040003e, 0x3c020008, 
+0x2221024, 0x10400020, 0x36100002, 0x3c020001, 0x431021, 0x8c427130, 
+0x10400005, 0x36100020, 0x36100100, 0x3c020020, 0x80050af, 0x2228825, 
+0x2402feff, 0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, 
+0x3c010001, 0x220821, 0x8c227138, 0x10400005, 0x3c020001, 0x2629825, 
+0x3c020080, 0x80050ce, 0x2228825, 0x3c02fffe, 0x3442ffff, 0x2629824, 
+0x3c02ff7f, 0x3442ffff, 0x80050ce, 0x2228824, 0x2402fedf, 0x2028024, 
+0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff, 0x2228824, 
+0x3c010001, 0x230821, 0xac207130, 0x3c010001, 0x230821, 0xac207138, 
+0xc00478a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 
+0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 0x80050e5, 
+0x141140, 0x8f820200, 0x2403fffd, 0x431024, 0xc00478a, 0xaf820200, 
+0x3c02bfff, 0x3442ffff, 0xc00428b, 0x2228824, 0x141140, 0x3c010001, 
+0x220821, 0x8005137, 0xac317124, 0x149140, 0x3c040001, 0x922021, 
+0x8c847128, 0x3c110001, 0x2328821, 0x8e317120, 0x3c024000, 0x821024, 
+0x14400011, 0x0, 0x3c020001, 0x8c425098, 0x14400006, 0x3c02bfff, 
+0x8f820200, 0x34420002, 0xc00478a, 0xaf820200, 0x3c02bfff, 0x3442ffff, 
+0xc00428b, 0x2228824, 0x3c010001, 0x320821, 0x8005137, 0xac317120, 
+0x3c020001, 0x8c425098, 0x1440002d, 0x141140, 0x3c020020, 0x821024, 
+0x10400007, 0x36100020, 0x24020100, 0x3c010001, 0x320821, 0xac227134, 
+0x8005117, 0x36100100, 0x3c010001, 0x320821, 0xac207134, 0x2402feff, 
+0x2028024, 0x3c020080, 0x821024, 0x10400007, 0x141940, 0x3c020001, 
+0x3c010001, 0x230821, 0xac22713c, 0x8005128, 0x2629825, 0x141140, 
+0x3c010001, 0x220821, 0xac20713c, 0x3c02fffe, 0x3442ffff, 0x2629824, 
+0xc00478a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 
+0x431024, 0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, 0x141140, 
+0x3c010001, 0x220821, 0xac317120, 0x8fbf0024, 0x8fb40020, 0x8fb3001c, 
+0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x0, 
+0x0 };
+u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __init = {
 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, 0x6f6e2041, 
 0x63654e49, 0x43205600, 0x42424242, 0x0, 0x0, 0x0, 
 0x135430, 0x13e7fc, 0x0, 0x0, 0x0, 0x0, 
@@ -2792,7 +2814,7 @@
 0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x30001, 0x1, 
 0x30201, 0x0, 0x0 };
-u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] = {
+u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __init = {
 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f66, 0x776d6169, 
 0x6e2e632c, 0x7620312e, 0x312e322e, 0x31312031, 0x3939382f, 0x30342f32, 
@@ -2813,114 +2835,114 @@
 0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x0, 0x0, 
 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f63, 0x6f6d6d61, 
-0x6e642e63, 0x2c762031, 0x2e312e32, 0x2e382031, 0x3939382f, 0x30342f32, 
-0x37203232, 0x3a31333a, 0x33392073, 0x6875616e, 0x67204578, 0x70202400, 
-0x4e4f636f, 0x6d616e64, 0x0, 0x68737465, 0x5f455252, 0x0, 
-0x412d4572, 0x72427563, 0x0, 0x4552524f, 0x522d4164, 0x64000000, 
-0x656e714d, 0x45765046, 0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 
-0x6661696c, 0x456e454d, 0x0, 0x442d4572, 0x724c6173, 0x74000000, 
-0x442d4572, 0x72320000, 0x6d437374, 0x4d644552, 0x52000000, 0x70726f6d, 
-0x4d644552, 0x52000000, 0x46696c74, 0x4d644552, 0x52000000, 0x636d645f, 
-0x45525200, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 
-0x6576526e, 0x6746756c, 0x6c000000, 0x0, 0x6da4, 0x7e7c, 
-0x6d3c, 0x85c8, 0x815c, 0x8614, 0x8614, 0x6e58, 
-0x7578, 0x7dcc, 0x7f68, 0x7f34, 0x8614, 0x7d30, 
-0x7f8c, 0x6d68, 0x808c, 0x0, 0x24486561, 0x6465723a, 
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
-0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6d612e63, 0x2c762031, 0x2e312e32, 
-0x2e332031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x34312073, 
-0x6875616e, 0x67204578, 0x70202400, 0x646d6172, 0x6441544e, 0x0, 
-0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0, 
-0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
-0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f74, 0x72616365, 
-0x2e632c76, 0x20312e31, 0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 
-0x32323a31, 0x333a3530, 0x20736875, 0x616e6720, 0x45787020, 0x24000000, 
-0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
-0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6174612e, 
-0x632c7620, 0x312e312e, 0x322e3220, 0x31393938, 0x2f30342f, 0x32372032, 
-0x323a3133, 0x3a343020, 0x73687561, 0x6e672045, 0x78702024, 0x0, 
-0x46575f56, 0x45525349, 0x4f4e3a20, 0x23312046, 0x7269204f, 0x63742031, 
-0x36203130, 0x3a31333a, 0x30352050, 0x44542031, 0x39393800, 0x46575f43, 
-0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031303a, 0x31333a30, 0x35000000, 
-0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 
-0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 
-0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, 
-0x6e672e61, 0x6374656f, 0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 
-0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, 0x20322e37, 0x2e320000, 
+0x6e642e63, 0x2c762031, 0x2e312e31, 0x362e3120, 0x31393938, 0x2f31312f, 
+0x31392030, 0x323a3339, 0x3a323520, 0x73687561, 0x6e672045, 0x78702024, 
+0x0, 0x3f4d626f, 0x78457674, 0x0, 0x4e4f636f, 0x6d616e64, 
+0x0, 0x68737465, 0x5f455252, 0x0, 0x412d4572, 0x72427563, 
+0x0, 0x4552524f, 0x522d4164, 0x64000000, 0x656e714d, 0x45765046, 
+0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, 
+0x0, 0x442d4572, 0x724c6173, 0x74000000, 0x442d4572, 0x72320000, 
+0x6d437374, 0x4d644552, 0x52000000, 0x70726f6d, 0x4d644552, 0x52000000, 
+0x46696c74, 0x4d644552, 0x52000000, 0x636d645f, 0x45525200, 0x3f456e71, 
+0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6576526e, 0x6746756c, 
+0x6c000000, 0x0, 0x6e90, 0x7fac, 0x6e28, 0x871c, 
+0x8298, 0x8768, 0x8768, 0x6f44, 0x7684, 0x7efc, 
+0x8098, 0x8064, 0x8768, 0x7e60, 0x80bc, 0x6e54, 
+0x81bc, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 
+0x6f6e2f64, 0x6d612e63, 0x2c762031, 0x2e312e32, 0x2e332031, 0x3939382f, 
+0x30342f32, 0x37203232, 0x3a31333a, 0x34312073, 0x6875616e, 0x67204578, 
+0x70202400, 0x646d6172, 0x6441544e, 0x0, 0x646d6177, 0x7241544e, 
 0x0, 0x0, 0x0, 0x0, 0x24486561, 0x6465723a, 
 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
-0x2f66772f, 0x636f6d6d, 0x6f6e2f6d, 0x656d2e63, 0x2c762031, 0x2e312e32, 
-0x2e322031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x34342073, 
-0x6875616e, 0x67204578, 0x70202400, 0x0, 0x24486561, 0x6465723a, 
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
-0x2f66772f, 0x636f6d6d, 0x6f6e2f73, 0x656e642e, 0x632c7620, 0x312e312e, 
-0x322e3820, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343820, 
-0x73687561, 0x6e672045, 0x78702024, 0x0, 0x736e6464, 0x654e6f51, 
-0x20000000, 0x6e6f454e, 0x515f5458, 0x0, 0x736e6464, 0x744e6f51, 
-0x20000000, 0x3f6e6f51, 0x64547845, 0x0, 0x756e6b72, 0x64747970, 
-0x65000000, 0x0, 0xba70, 0xba70, 0xbb18, 0xac2c, 
-0xae2c, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 
-0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 0xbb18, 
-0xbb18, 0xbb18, 0xbb18, 0xae14, 0x24486561, 0x6465723a, 
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
-0x2f66772f, 0x636f6d6d, 0x6f6e2f72, 0x6563762e, 0x632c7620, 0x312e312e, 
-0x322e3139, 0x20313939, 0x382f3037, 0x2f323420, 0x32313a33, 0x303a3035, 
-0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x706b5278, 0x45525200, 
-0x66726d32, 0x4c617267, 0x65000000, 0x72784e6f, 0x52784264, 0x0, 
-0x72785144, 0x6d614446, 0x0, 0x72785144, 0x6d614246, 0x0, 
-0x3f6e6f51, 0x64527845, 0x0, 0x706b5278, 0x45525273, 0x0, 
-0x66726d32, 0x4c726753, 0x0, 0x72784e6f, 0x42645300, 0x3f724264, 
-0x446d6146, 0x0, 0x3f724a42, 0x64446d46, 0x0, 0x0, 
-0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 
-0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 0xf3c0, 
-0xf3c0, 0xf3c0, 0xf3c0, 0xf3b8, 0xf3b8, 0xf3b8, 
-0x572d444d, 0x41456e46, 0x0, 0x0, 0xfafc, 0xfe80, 
-0xfb18, 0xfe80, 0xfe80, 0xfe80, 0xfe80, 0xfe80, 
-0xfe80, 0xf44c, 0xfe80, 0xfe80, 0xfe80, 0xfe80, 
-0xfe80, 0xfe78, 0xfe78, 0xfe78, 0x24486561, 0x6465723a, 
+0x2f66772f, 0x636f6d6d, 0x6f6e2f74, 0x72616365, 0x2e632c76, 0x20312e31, 
+0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 0x32323a31, 0x333a3530, 
+0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x24486561, 0x6465723a, 
 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
-0x2f66772f, 0x636f6d6d, 0x6f6e2f6d, 0x61632e63, 0x2c762031, 0x2e312e32, 
-0x2e313220, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343220, 
-0x73687561, 0x6e672045, 0x78702024, 0x0, 0x6d616374, 0x7841544e, 
-0x0, 0x4e745379, 0x6e264c6b, 0x0, 0x72656d61, 0x73737274, 
-0x0, 0x6c696e6b, 0x444f574e, 0x0, 0x656e714d, 0x45765046, 
-0x61696c00, 0x656e714d, 0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, 
-0x0, 0x6c696e6b, 0x55500000, 0x0, 0x24486561, 0x6465723a, 
-0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
-0x2f66772f, 0x636f6d6d, 0x6f6e2f63, 0x6b73756d, 0x2e632c76, 0x20312e31, 
-0x2e322e32, 0x20313939, 0x382f3034, 0x2f323720, 0x32323a31, 0x333a3339, 
-0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x50726f62, 0x65506879, 
-0x0, 0x6c6e6b41, 0x53535254, 0x0, 0x11680, 0x116b8, 
-0x116dc, 0x11710, 0x1173c, 0x11750, 0x1178c, 0x11ac4, 
-0x11864, 0x118a4, 0x118d4, 0x11914, 0x11944, 0x11980, 
-0x119c4, 0x11ac4, 0x0, 0x0, 0x11f5c, 0x1202c, 
-0x12104, 0x121d4, 0x12230, 0x1230c, 0x12334, 0x12410, 
-0x12438, 0x125e0, 0x12608, 0x127b0, 0x129a8, 0x12c3c, 
-0x12b50, 0x12c3c, 0x12c68, 0x127d8, 0x12980, 0x0, 
-0x13054, 0x130b4, 0x13130, 0x1315c, 0x131ac, 0x131e8, 
-0x1321c, 0x132a8, 0x13360, 0x13430, 0x13470, 0x134f4, 
-0x13550, 0x13684, 0x646f4261, 0x73655067, 0x0, 0x0, 
-0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, 0x0, 
-0x0 };
+0x2f66772f, 0x636f6d6d, 0x6f6e2f64, 0x6174612e, 0x632c7620, 0x312e312e, 
+0x322e3220, 0x31393938, 0x2f30342f, 0x32372032, 0x323a3133, 0x3a343020, 
+0x73687561, 0x6e672045, 0x78702024, 0x0, 0x46575f56, 0x45525349, 
+0x4f4e3a20, 0x2331204d, 0x6f6e2044, 0x65632037, 0x2031343a, 0x35363a33, 
+0x30205053, 0x54203139, 0x39380000, 0x46575f43, 0x4f4d5049, 0x4c455f54, 
+0x494d453a, 0x2031343a, 0x35363a33, 0x30000000, 0x46575f43, 0x4f4d5049, 
+0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 
+0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 0x0, 0x46575f43, 
+0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f, 
+0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 0x4c45523a, 0x20676363, 
+0x20766572, 0x73696f6e, 0x20322e37, 0x2e320000, 0x0, 0x0, 
+0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 
+0x6f6e2f6d, 0x656d2e63, 0x2c762031, 0x2e312e32, 0x2e322031, 0x3939382f, 
+0x30342f32, 0x37203232, 0x3a31333a, 0x34342073, 0x6875616e, 0x67204578, 
+0x70202400, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 
+0x6f6e2f73, 0x656e642e, 0x632c7620, 0x312e312e, 0x322e3820, 0x31393938, 
+0x2f30342f, 0x32372032, 0x323a3133, 0x3a343820, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x736e6464, 0x654e6f51, 0x20000000, 0x6e6f454e, 
+0x515f5458, 0x0, 0x736e6464, 0x744e6f51, 0x20000000, 0x3f6e6f51, 
+0x64547845, 0x0, 0x756e6b72, 0x64747970, 0x65000000, 0x0, 
+0xbc88, 0xbc88, 0xbd30, 0xae2c, 0xb038, 0xbd30, 
+0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 
+0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 0xbd30, 
+0xbd30, 0xb020, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 
+0x6f6e2f72, 0x6563762e, 0x632c7620, 0x312e312e, 0x322e3139, 0x20313939, 
+0x382f3037, 0x2f323420, 0x32313a33, 0x303a3035, 0x20736875, 0x616e6720, 
+0x45787020, 0x24000000, 0x706b5278, 0x45525200, 0x66726d32, 0x4c617267, 
+0x65000000, 0x72784e6f, 0x52784264, 0x0, 0x72785144, 0x6d614446, 
+0x0, 0x72785144, 0x6d614246, 0x0, 0x3f6e6f51, 0x64527845, 
+0x0, 0x706b5278, 0x45525273, 0x0, 0x66726d32, 0x4c726753, 
+0x0, 0x72784e6f, 0x42645300, 0x3f724264, 0x446d6146, 0x0, 
+0x3f724a42, 0x64446d46, 0x0, 0x0, 0xf638, 0xf638, 
+0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 
+0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 0xf638, 
+0xf638, 0xf630, 0xf630, 0xf630, 0x572d444d, 0x41456e46, 
+0x0, 0x0, 0xfd80, 0x1011c, 0xfd9c, 0x1011c, 
+0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x1011c, 0xf6c4, 
+0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x1011c, 0x10114, 
+0x10114, 0x10114, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 
+0x6f6e2f6d, 0x61632e63, 0x2c762031, 0x2e312e32, 0x2e313220, 0x31393938, 
+0x2f30342f, 0x32372032, 0x323a3133, 0x3a343220, 0x73687561, 0x6e672045, 
+0x78702024, 0x0, 0x6d616374, 0x7841544e, 0x0, 0x4e745379, 
+0x6e264c6b, 0x0, 0x72656d61, 0x73737274, 0x0, 0x6c696e6b, 
+0x444f574e, 0x0, 0x656e714d, 0x45765046, 0x61696c00, 0x656e714d, 
+0x45764661, 0x696c0000, 0x6661696c, 0x456e454d, 0x0, 0x6c696e6b, 
+0x55500000, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
+0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f66772f, 0x636f6d6d, 
+0x6f6e2f63, 0x6b73756d, 0x2e632c76, 0x20312e31, 0x2e322e32, 0x20313939, 
+0x382f3034, 0x2f323720, 0x32323a31, 0x333a3339, 0x20736875, 0x616e6720, 
+0x45787020, 0x24000000, 0x50726f62, 0x65506879, 0x0, 0x6c6e6b41, 
+0x53535254, 0x0, 0x11880, 0x118b8, 0x118dc, 0x11910, 
+0x1193c, 0x11950, 0x1198c, 0x11cc4, 0x11a64, 0x11aa4, 
+0x11ad4, 0x11b14, 0x11b44, 0x11b80, 0x11bc4, 0x11cc4, 
+0x0, 0x0, 0x1215c, 0x1222c, 0x12304, 0x123d4, 
+0x12430, 0x1250c, 0x12534, 0x12610, 0x12638, 0x127e0, 
+0x12808, 0x129b0, 0x12ba8, 0x12e3c, 0x12d50, 0x12e3c, 
+0x12e68, 0x129d8, 0x12b80, 0x0, 0x13254, 0x132b4, 
+0x13330, 0x1335c, 0x133ac, 0x133e8, 0x1341c, 0x134a8, 
+0x13560, 0x13630, 0x13670, 0x136f4, 0x13750, 0x13884, 
+0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 
+0x73746d61, 0x634c4e4b, 0x0, 0x0, 0x0 };
 /* Generated by genfw.c */
 int tigon2FwReleaseMajor = 0xc;
 int tigon2FwReleaseMinor = 0x1;
-int tigon2FwReleaseFix = 0x4;
+int tigon2FwReleaseFix = 0x6;
 u32 tigon2FwStartAddr = 0x4000;
 u32 tigon2FwTextAddr = 0x4000;
-int tigon2FwTextLen = 0xe480;
-u32 tigon2FwDataAddr = 0x131d0;
+int tigon2FwTextLen = 0xe5b0;
+u32 tigon2FwDataAddr = 0x13330;
 int tigon2FwDataLen = 0x170;
-u32 tigon2FwRodataAddr = 0x12480;
-int tigon2FwRodataLen = 0xd30;
-u32 tigon2FwBssAddr = 0x133f0;
+u32 tigon2FwRodataAddr = 0x125b0;
+int tigon2FwRodataLen = 0xd60;
+u32 tigon2FwBssAddr = 0x13550;
 int tigon2FwBssLen = 0x20c0;
-u32 tigon2FwSbssAddr = 0x13340;
+u32 tigon2FwSbssAddr = 0x134a0;
 int tigon2FwSbssLen = 0xa8;
-u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] = {
+u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __init = {
 0x0, 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, 
-0x8fbd3220, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, 
-0xd, 0x3c1d0001, 0x8fbd3224, 0x3a0f021, 0x3c100000, 0x26104000, 
+0x8fbd3380, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, 
+0xd, 0x3c1d0001, 0x8fbd3384, 0x3a0f021, 0x3c100000, 0x26104000, 
 0xc0016fe, 0x0, 0xd, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
@@ -2930,14 +2952,14 @@
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x2000008, 0x0, 
 0x8001671, 0x3c0a0001, 0x8001671, 0x3c0a0002, 0x8001671, 0x0, 
-0x8002994, 0x0, 0x8001671, 0x3c0a0003, 0x8001671, 0x3c0a0004, 
-0x8003110, 0x0, 0x80019ba, 0x0, 0x8003608, 0x0, 
-0x8003597, 0x0, 0x8001671, 0x3c0a0006, 0x8001671, 0x3c0a0007, 
-0x8001671, 0x3c0a0008, 0x8001671, 0x3c0a0009, 0x8003679, 0x0, 
-0x8002bd5, 0x0, 0x8001671, 0x3c0a000b, 0x8001671, 0x3c0a000c, 
-0x8001671, 0x3c0a000d, 0x80026e0, 0x0, 0x80026b3, 0x0, 
+0x80029b8, 0x0, 0x8001671, 0x3c0a0003, 0x8001671, 0x3c0a0004, 
+0x8003134, 0x0, 0x80019ba, 0x0, 0x8003653, 0x0, 
+0x80035e2, 0x0, 0x8001671, 0x3c0a0006, 0x8001671, 0x3c0a0007, 
+0x8001671, 0x3c0a0008, 0x8001671, 0x3c0a0009, 0x80036c4, 0x0, 
+0x8002bf9, 0x0, 0x8001671, 0x3c0a000b, 0x8001671, 0x3c0a000c, 
+0x8001671, 0x3c0a000d, 0x80026ee, 0x0, 0x80026ad, 0x0, 
 0x8001671, 0x3c0a000e, 0x8001f40, 0x0, 0x80018c9, 0x0, 
-0x800196b, 0x0, 0x80038f7, 0x0, 0x80038e1, 0x0, 
+0x800196b, 0x0, 0x8003943, 0x0, 0x800392d, 0x0, 
 0x8001671, 0x0, 0x800184d, 0x0, 0x8001893, 0x0, 
 0x8001671, 0x3c0a0013, 0x8001671, 0x3c0a0014, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
@@ -2950,68 +2972,68 @@
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
-0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xc0028d0, 0xd021, 0x8f820040, 
+0x27bdffe0, 0x3c1cc000, 0xafbf0018, 0xc0028f4, 0xd021, 0x8f820040, 
 0x3c03f000, 0x431824, 0x3c025000, 0x10620005, 0x3c026000, 0x1062001a, 
 0x24020003, 0x10000030, 0x0, 0x8f820050, 0x3c030010, 0x431024, 
-0x50400013, 0x24020003, 0x3c030001, 0x2463c2d0, 0x3c020001, 0x2442c354, 
-0x431023, 0x3c010001, 0xac2333b8, 0x8f830140, 0x3c040001, 0x2484c35c, 
-0x3c010001, 0xac2233a4, 0x3c020001, 0x2442c3c4, 0x3c010001, 0xac2031d8, 
-0x10000013, 0x441023, 0x3c030001, 0x2463c3cc, 0xaf8200ec, 0x3c020001, 
-0x2442c408, 0x431023, 0x3c010001, 0xac2333b8, 0x8f830140, 0x3c040001, 
-0x2484c410, 0x3c010001, 0xac2233a4, 0x3c020001, 0x2442c438, 0x441023, 
-0x3c0100c0, 0xac203ffc, 0x3c010001, 0xac2433b0, 0x3c010001, 0xac2233ac, 
+0x50400013, 0x24020003, 0x3c030001, 0x2463c360, 0x3c020001, 0x2442c3e4, 
+0x431023, 0x3c010001, 0xac233518, 0x8f830140, 0x3c040001, 0x2484c3ec, 
+0x3c010001, 0xac223504, 0x3c020001, 0x2442c454, 0x3c010001, 0xac203338, 
+0x10000013, 0x441023, 0x3c030001, 0x2463c45c, 0xaf8200ec, 0x3c020001, 
+0x2442c498, 0x431023, 0x3c010001, 0xac233518, 0x8f830140, 0x3c040001, 
+0x2484c4a0, 0x3c010001, 0xac223504, 0x3c020001, 0x2442c4c8, 0x441023, 
+0x3c0100c0, 0xac203ffc, 0x3c010001, 0xac243510, 0x3c010001, 0xac22350c, 
 0x34630004, 0xaf830140, 0xc00169c, 0x0, 0x402821, 0x3c010001, 
-0xac253350, 0x3c020008, 0x10a2002c, 0x45102b, 0x14400006, 0x3c020010, 
+0xac2534b0, 0x3c020008, 0x10a2002c, 0x45102b, 0x14400006, 0x3c020010, 
 0x3c020004, 0x10a20007, 0x3c02ffff, 0x1000005b, 0x0, 0x10a20045, 
-0x3c030003, 0x10000057, 0x0, 0x34422e10, 0x3c030001, 0x246354b0, 
-0x3c040001, 0x8c8431d4, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8, 
-0x2403f000, 0xa32824, 0x51082, 0x431024, 0x3c010001, 0xac223340, 
-0xa21023, 0x3c010001, 0xac223348, 0x3402a000, 0x3c010001, 0xac223358, 
-0x24020008, 0x3c010001, 0xac223360, 0x2402001f, 0x3c010001, 0xac223368, 
-0x24020016, 0x3c010001, 0xac22334c, 0x10000041, 0x3c08ffff, 0x3c02ffff, 
-0x34422e10, 0x3c030001, 0x246354b0, 0x3c040001, 0x8c8431d4, 0xa31823, 
+0x3c030003, 0x10000057, 0x0, 0x34422e10, 0x3c030001, 0x24635610, 
+0x3c040001, 0x8c843334, 0xa31823, 0x14800002, 0x622821, 0x24a5faa8, 
+0x2403f000, 0xa32824, 0x51082, 0x431024, 0x3c010001, 0xac2234a0, 
+0xa21023, 0x3c010001, 0xac2234a8, 0x3402a000, 0x3c010001, 0xac2234b8, 
+0x24020008, 0x3c010001, 0xac2234c0, 0x2402001f, 0x3c010001, 0xac2234c8, 
+0x24020016, 0x3c010001, 0xac2234ac, 0x10000041, 0x3c08ffff, 0x3c02ffff, 
+0x34422e10, 0x3c030001, 0x24635610, 0x3c040001, 0x8c843334, 0xa31823, 
 0x14800002, 0x622821, 0x24a5faa8, 0x2403f000, 0xa32824, 0x3c040003, 
-0x34842000, 0x510c2, 0x431024, 0x3c010001, 0xac223340, 0xa21023, 
-0x3c010001, 0xac223348, 0x24020008, 0x3c010001, 0xac223360, 0x2402001f, 
-0x3c010001, 0xac223368, 0x24020016, 0x3c010001, 0xac243358, 0x3c010001, 
-0xac22334c, 0x1000001f, 0x3c08ffff, 0x34632000, 0x3c020001, 0x3c010001, 
-0xac223340, 0x3c020007, 0x3c010001, 0xac223348, 0x24020008, 0x3c010001, 
-0xac223360, 0x2402001f, 0x3c010001, 0xac223368, 0x24020016, 0x3c010001, 
-0xac233358, 0x3c010001, 0xac22334c, 0x1000000b, 0x3c08ffff, 0x3c040001, 
-0x24842540, 0x3c050001, 0x8ca53350, 0x3021, 0x3821, 0xafa00010, 
-0xc0028eb, 0xafa00014, 0x3c08ffff, 0x35087e10, 0x3c0500bf, 0x34a5f000, 
-0x3c0600bf, 0x34c6e000, 0x3c070001, 0x8ce73340, 0x3c040001, 0x8c843348, 
-0x3c030020, 0x3c090001, 0x8d2931d0, 0x671023, 0x441023, 0x245bb000, 
-0x641823, 0x3c010001, 0xac233354, 0x671823, 0x27620ffc, 0x3c010001, 
-0xac223220, 0x27621ffc, 0xbb2823, 0xdb3023, 0x3c010001, 0xac233344, 
-0x3c010001, 0xac223224, 0xaf850150, 0xaf860250, 0x1120001b, 0x368b821, 
-0x33620fff, 0x10400008, 0x24050019, 0x3c040001, 0x2484254c, 0x3603021, 
-0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x3c1d0001, 0x8fbd31dc, 
-0x3a0f021, 0xc001684, 0x0, 0x3c020001, 0x8c4231e0, 0x3c030001, 
-0x8c6331e4, 0x2442fe00, 0x24630200, 0x3c010001, 0xac2231e0, 0x3c010001, 
-0x10000004, 0xac2331e4, 0x3c1d0001, 0x8fbd3220, 0x3a0f021, 0x3c020001, 
-0x8c4231d4, 0x1040000d, 0x26f6faa8, 0x3c020001, 0x8c4231e0, 0x3c030001, 
-0x8c6331e4, 0x3c160001, 0x8ed631e4, 0x2442faa8, 0x24630558, 0x3c010001, 
-0xac2231e0, 0x3c010001, 0xac2331e4, 0x3c020001, 0x8c4231d8, 0x14400003, 
-0x0, 0x3c010001, 0xac2031e0, 0xc0011ca, 0x0, 0x8fbf0018, 
+0x34842000, 0x510c2, 0x431024, 0x3c010001, 0xac2234a0, 0xa21023, 
+0x3c010001, 0xac2234a8, 0x24020008, 0x3c010001, 0xac2234c0, 0x2402001f, 
+0x3c010001, 0xac2234c8, 0x24020016, 0x3c010001, 0xac2434b8, 0x3c010001, 
+0xac2234ac, 0x1000001f, 0x3c08ffff, 0x34632000, 0x3c020001, 0x3c010001, 
+0xac2234a0, 0x3c020007, 0x3c010001, 0xac2234a8, 0x24020008, 0x3c010001, 
+0xac2234c0, 0x2402001f, 0x3c010001, 0xac2234c8, 0x24020016, 0x3c010001, 
+0xac2334b8, 0x3c010001, 0xac2234ac, 0x1000000b, 0x3c08ffff, 0x3c040001, 
+0x24842670, 0x3c050001, 0x8ca534b0, 0x3021, 0x3821, 0xafa00010, 
+0xc00290f, 0xafa00014, 0x3c08ffff, 0x35087e10, 0x3c0500bf, 0x34a5f000, 
+0x3c0600bf, 0x34c6e000, 0x3c070001, 0x8ce734a0, 0x3c040001, 0x8c8434a8, 
+0x3c030020, 0x3c090001, 0x8d293330, 0x671023, 0x441023, 0x245bb000, 
+0x641823, 0x3c010001, 0xac2334b4, 0x671823, 0x27620ffc, 0x3c010001, 
+0xac223380, 0x27621ffc, 0xbb2823, 0xdb3023, 0x3c010001, 0xac2334a4, 
+0x3c010001, 0xac223384, 0xaf850150, 0xaf860250, 0x1120001b, 0x368b821, 
+0x33620fff, 0x10400008, 0x24050019, 0x3c040001, 0x2484267c, 0x3603021, 
+0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x3c1d0001, 0x8fbd333c, 
+0x3a0f021, 0xc001684, 0x0, 0x3c020001, 0x8c423340, 0x3c030001, 
+0x8c633344, 0x2442fe00, 0x24630200, 0x3c010001, 0xac223340, 0x3c010001, 
+0x10000004, 0xac233344, 0x3c1d0001, 0x8fbd3380, 0x3a0f021, 0x3c020001, 
+0x8c423334, 0x1040000d, 0x26f6faa8, 0x3c020001, 0x8c423340, 0x3c030001, 
+0x8c633344, 0x3c160001, 0x8ed63344, 0x2442faa8, 0x24630558, 0x3c010001, 
+0xac223340, 0x3c010001, 0xac233344, 0x3c020001, 0x8c423338, 0x14400003, 
+0x0, 0x3c010001, 0xac203340, 0xc0011ca, 0x0, 0x8fbf0018, 
 0x3e00008, 0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb50058, 
 0xafb30054, 0xafb10050, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 
-0x3c020001, 0x8c4231e0, 0x3c030001, 0x8c6331e4, 0xaf800048, 0x8f840048, 
+0x3c020001, 0x8c423340, 0x3c030001, 0x8c633344, 0xaf800048, 0x8f840048, 
 0x3c120000, 0x26524100, 0xa3a00047, 0xafa20034, 0x14800005, 0xafa30030, 
 0xaf800048, 0x8f820048, 0x10400004, 0x0, 0xaf800048, 0x10000003, 
-0x2e02021, 0xaf80004c, 0x2e02021, 0xc00296c, 0x340581f0, 0x2c02021, 
-0xc00296c, 0x24050558, 0x3c020001, 0x8c423344, 0x3c030001, 0x8c633340, 
-0x3c040001, 0x8c843348, 0x3c050001, 0x8ca53358, 0x3c060001, 0x8cc63360, 
-0x3c070001, 0x8ce73368, 0x3c080001, 0x8d08334c, 0xaec20534, 0x3c020001, 
-0x8c423354, 0x8ec90534, 0xaec50544, 0x3c050001, 0x8ca53350, 0xaec00000, 
+0x2e02021, 0xaf80004c, 0x2e02021, 0xc002990, 0x340581f0, 0x2c02021, 
+0xc002990, 0x24050558, 0x3c020001, 0x8c4234a4, 0x3c030001, 0x8c6334a0, 
+0x3c040001, 0x8c8434a8, 0x3c050001, 0x8ca534b8, 0x3c060001, 0x8cc634c0, 
+0x3c070001, 0x8ce734c8, 0x3c080001, 0x8d0834ac, 0xaec20534, 0x3c020001, 
+0x8c4234b4, 0x8ec90534, 0xaec50544, 0x3c050001, 0x8ca534b0, 0xaec00000, 
 0xaec3053c, 0xaec40540, 0xaec60548, 0xaec7054c, 0xaec80550, 0xaec20538, 
 0xafa90010, 0x8ec20538, 0xafa20014, 0x8ec6053c, 0x8ec70540, 0x3c040001, 
-0xc0028eb, 0x24842558, 0xafb70010, 0xafb60014, 0x8ec60544, 0x8ec70548, 
-0x3c040001, 0x24842560, 0xc0028eb, 0x24050001, 0x3c040001, 0x24842568, 
-0x24050001, 0x24060001, 0x24070001, 0xafa00010, 0xc0028eb, 0xafa00014, 
-0x3c020001, 0x8c423350, 0x3603821, 0x3c060001, 0x24c654b0, 0x2448ffff, 
+0xc00290f, 0x24842688, 0xafb70010, 0xafb60014, 0x8ec60544, 0x8ec70548, 
+0x3c040001, 0x24842690, 0xc00290f, 0x24050001, 0x3c040001, 0x24842698, 
+0x24050001, 0x24060001, 0x24070001, 0xafa00010, 0xc00290f, 0xafa00014, 
+0x3c020001, 0x8c4234b0, 0x3603821, 0x3c060001, 0x24c65610, 0x2448ffff, 
 0x1061824, 0xe81024, 0x43102b, 0x10400006, 0x24050002, 0x3c040001, 
-0x24842570, 0xafa80010, 0xc0028eb, 0xafa00014, 0x24020001, 0xa2c20529, 
+0x248426a0, 0xafa80010, 0xc00290f, 0xafa00014, 0x24020001, 0xa2c20529, 
 0xaf800054, 0xaf80011c, 0x8f420218, 0x30420002, 0x10400009, 0x0, 
 0x8f420220, 0x3c030002, 0x34630004, 0x431025, 0xaec20008, 0x8f42021c, 
 0x10000008, 0x34420004, 0x8f420220, 0x3c030002, 0x34630006, 0x431025, 
@@ -3028,109 +3050,109 @@
 0x9482000a, 0xaca2009c, 0x8ca200b0, 0x8ec30010, 0x431025, 0xaca200b0, 
 0x8f8200b0, 0x30420004, 0x1440fffd, 0x0, 0x8ee20448, 0x8ee3044c, 
 0xaee304bc, 0x8ee204bc, 0x2442e000, 0x2c422001, 0x1440000d, 0x26c40128, 
-0x8ee20448, 0x8ee3044c, 0x3c040001, 0x2484257c, 0x3c050001, 0xafa00010, 
-0xafa00014, 0x8ee704bc, 0x34a5f000, 0xc0028eb, 0x603021, 0x26c40128, 
-0xc00296c, 0x24050400, 0x27440080, 0xc00296c, 0x24050080, 0x8f42025c, 
-0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xc00297e, 
+0x8ee20448, 0x8ee3044c, 0x3c040001, 0x248426ac, 0x3c050001, 0xafa00010, 
+0xafa00014, 0x8ee704bc, 0x34a5f000, 0xc00290f, 0x603021, 0x26c40128, 
+0xc002990, 0x24050400, 0x27440080, 0xc002990, 0x24050080, 0x8f42025c, 
+0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xc0029a2, 
 0xaec20160, 0x3c043b9a, 0x3484ca00, 0x2821, 0x24020006, 0x24030002, 
 0xaec2015c, 0x240203e8, 0xaec3016c, 0xaec30168, 0xaec40164, 0xaec201fc, 
-0x24020001, 0xaec301f8, 0xaec20204, 0x3c030001, 0x651821, 0x906331e8, 
+0x24020001, 0xaec301f8, 0xaec20204, 0x3c030001, 0x651821, 0x90633348, 
 0x2c51021, 0x24a50001, 0xa0430194, 0x2ca2000f, 0x1440fff8, 0x2c51821, 
 0x8f820040, 0x24a50001, 0x21702, 0x24420030, 0xa0620194, 0x2c51021, 
-0xa0400194, 0xafa00010, 0x8fa20034, 0x3c040001, 0x24842588, 0xafa20014, 
-0x8fa60030, 0x3821, 0xc0028eb, 0x2821, 0x3c040000, 0x24845990, 
+0xa0400194, 0xafa00010, 0x8fa20034, 0x3c040001, 0x248426b8, 0xafa20014, 
+0x8fa60030, 0x3821, 0xc00290f, 0x2821, 0x3c040000, 0x24845990, 
 0x24050010, 0x27b30030, 0x2603021, 0x27b10034, 0xc0016be, 0x2203821, 
-0x3c030001, 0x8c6331d8, 0x3c15f000, 0x1060000a, 0xafa2003c, 0x8fa30030, 
+0x3c030001, 0x8c633338, 0x3c15f000, 0x1060000a, 0xafa2003c, 0x8fa30030, 
 0x2405ff00, 0x8fa20034, 0x246400ff, 0x852024, 0x831823, 0x431023, 
 0xafa20034, 0xafa40030, 0x3c040000, 0x24844100, 0x24050108, 0x2603021, 
 0xc0016be, 0x2203821, 0x96e30452, 0x30630003, 0x1060005f, 0x409021, 
 0x8f820050, 0x3c030010, 0x431024, 0x10400021, 0x0, 0x8f820040, 
 0x3c035000, 0x551024, 0x14430009, 0x0, 0x96e60452, 0x8f820050, 
-0xafa00014, 0xafa20010, 0x8f870040, 0x3c040001, 0x1000000d, 0x24842594, 
+0xafa00014, 0xafa20010, 0x8f870040, 0x3c040001, 0x1000000d, 0x248426c4, 
 0x8f420218, 0x30420040, 0x1040000d, 0x24020001, 0x8f820050, 0x96e60452, 
-0xafa20010, 0x8f420218, 0xafa20014, 0x8f870040, 0x3c040001, 0x2484259c, 
-0xc0028eb, 0x2821, 0x10000004, 0x0, 0x3c010001, 0x370821, 
-0xa02281ec, 0x3c040001, 0x24849a48, 0x3c050001, 0x24a59ac4, 0xa42823, 
+0xafa20010, 0x8f420218, 0xafa20014, 0x8f870040, 0x3c040001, 0x248426cc, 
+0xc00290f, 0x2821, 0x10000004, 0x0, 0x3c010001, 0x370821, 
+0xa02281ec, 0x3c040001, 0x24849a34, 0x3c050001, 0x24a59aac, 0xa42823, 
 0x27b30030, 0x2603021, 0x8ec3000c, 0x27b10034, 0x2203821, 0x24020001, 
 0xa2c20020, 0xa2c20021, 0x34630a00, 0xc0016be, 0xaec3000c, 0x3c040001, 
-0x2484ab64, 0x3c050001, 0x24a5af4c, 0xa42823, 0x2603021, 0x2203821, 
-0xc0016be, 0xaec200a4, 0x3c040001, 0x2484b418, 0x3c050001, 0x24a5c2c8, 
-0xa42823, 0x2603021, 0x3c010001, 0xac22339c, 0xc0016be, 0x2203821, 
-0x3c040001, 0x2484dacc, 0x3c050001, 0x24a5e290, 0xa42823, 0x2603021, 
-0x3c010001, 0xac2233a0, 0xc0016be, 0x2203821, 0x3c040001, 0x248425a4, 
-0x96e60452, 0x24050011, 0x3821, 0x3c010001, 0xac2233bc, 0xafa00010, 
-0xc0028eb, 0xafa00014, 0x10000028, 0x0, 0x3c040001, 0x2484989c, 
-0x3c050001, 0x24a59a40, 0xa42823, 0x2603021, 0xc0016be, 0x2203821, 
-0x3c040001, 0x2484a650, 0x3c050001, 0x24a5ab5c, 0xa42823, 0x2603021, 
-0x2203821, 0xc0016be, 0xaec200a4, 0x3c040001, 0x2484af54, 0x3c050001, 
-0x24a5b410, 0xa42823, 0x2603021, 0x3c010001, 0xac22339c, 0xc0016be, 
-0x2203821, 0x3c040001, 0x2484d9e4, 0x3c050001, 0x24a5dac4, 0xa42823, 
-0x2603021, 0x3c010001, 0xac2233a0, 0xc0016be, 0x2203821, 0x3c010001, 
-0xac2233bc, 0x3c020001, 0x8c42339c, 0x3c050fff, 0x34a5ffff, 0x3c030001, 
-0x8c6333a0, 0x3c040800, 0x451024, 0x21082, 0x441025, 0x651824, 
-0xae420020, 0x3c020001, 0x8c4233bc, 0x31882, 0x641825, 0xae430080, 
+0x2484abf4, 0x3c050001, 0x24a5afdc, 0xa42823, 0x2603021, 0x2203821, 
+0xc0016be, 0xaec200a4, 0x3c040001, 0x2484b4a8, 0x3c050001, 0x24a5c358, 
+0xa42823, 0x2603021, 0x3c010001, 0xac2234fc, 0xc0016be, 0x2203821, 
+0x3c040001, 0x2484dbf8, 0x3c050001, 0x24a5e3bc, 0xa42823, 0x2603021, 
+0x3c010001, 0xac223500, 0xc0016be, 0x2203821, 0x3c040001, 0x248426d4, 
+0x96e60452, 0x24050011, 0x3821, 0x3c010001, 0xac22351c, 0xafa00010, 
+0xc00290f, 0xafa00014, 0x10000028, 0x0, 0x3c040001, 0x24849890, 
+0x3c050001, 0x24a59a2c, 0xa42823, 0x2603021, 0xc0016be, 0x2203821, 
+0x3c040001, 0x2484a6e0, 0x3c050001, 0x24a5abec, 0xa42823, 0x2603021, 
+0x2203821, 0xc0016be, 0xaec200a4, 0x3c040001, 0x2484afe4, 0x3c050001, 
+0x24a5b4a0, 0xa42823, 0x2603021, 0x3c010001, 0xac2234fc, 0xc0016be, 
+0x2203821, 0x3c040001, 0x2484db10, 0x3c050001, 0x24a5dbf0, 0xa42823, 
+0x2603021, 0x3c010001, 0xac223500, 0xc0016be, 0x2203821, 0x3c010001, 
+0xac22351c, 0x3c020001, 0x8c4234fc, 0x3c050fff, 0x34a5ffff, 0x3c030001, 
+0x8c633500, 0x3c040800, 0x451024, 0x21082, 0x441025, 0x651824, 
+0xae420020, 0x3c020001, 0x8c42351c, 0x31882, 0x641825, 0xae430080, 
 0x451024, 0x21082, 0x441025, 0xae420078, 0x96e20462, 0x30420003, 
 0x14400009, 0x0, 0x96e20472, 0x30420003, 0x1040007f, 0x27b30030, 
 0x96e20462, 0x30420003, 0x1040006d, 0x3c020700, 0x96e20472, 0x30420003, 
 0x10400069, 0x3c020700, 0x96e30472, 0x96e20462, 0x14620065, 0x3c020700, 
 0x8f82005c, 0x3c030080, 0x431024, 0x1040000b, 0x0, 0x8f820050, 
 0x96e60462, 0xafa20010, 0x8f82005c, 0xafa20014, 0x8f870040, 0x3c040001, 
-0x248425b0, 0xc0028eb, 0x24051977, 0x8f820050, 0x3c030010, 0x431024, 
+0x248426e0, 0xc00290f, 0x24051977, 0x8f820050, 0x3c030010, 0x431024, 
 0x10400022, 0x0, 0x8f820040, 0x3c03f000, 0x431024, 0x3c035000, 
 0x14430009, 0x0, 0x96e60462, 0x8f820050, 0xafa00014, 0xafa20010, 
-0x8f870040, 0x3c040001, 0x1000000d, 0x24842594, 0x8f420218, 0x30420040, 
+0x8f870040, 0x3c040001, 0x1000000d, 0x248426c4, 0x8f420218, 0x30420040, 
 0x1040000d, 0x24020001, 0x8f820050, 0x96e60462, 0xafa20010, 0x8f420218, 
-0xafa20014, 0x8f870040, 0x3c040001, 0x2484259c, 0xc0028eb, 0x24050001, 
+0xafa20014, 0x8f870040, 0x3c040001, 0x248426cc, 0xc00290f, 0x24050001, 
 0x10000004, 0x0, 0x3c010001, 0x370821, 0xa02281ec, 0x3c040001, 
-0x2484981c, 0x3c050001, 0x24a59894, 0xa42823, 0x27b30030, 0x2603021, 
+0x24849810, 0x3c050001, 0x24a59888, 0xa42823, 0x27b30030, 0x2603021, 
 0x8ec30004, 0x27b10034, 0x2203821, 0x24020001, 0xa2c2004c, 0x34630e00, 
-0xc0016be, 0xaec30004, 0x3c040001, 0x2484cf2c, 0x3c050001, 0x24a5d654, 
+0xc0016be, 0xaec30004, 0x3c040001, 0x2484d058, 0x3c050001, 0x24a5d780, 
 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, 0x3c040001, 
-0x2484dacc, 0x3c050001, 0x24a5e290, 0xa42823, 0x2603021, 0x3c010001, 
-0xac2233b4, 0xc0016be, 0x2203821, 0x3c040001, 0x248425bc, 0x21900, 
+0x2484dbf8, 0x3c050001, 0x24a5e3bc, 0xa42823, 0x2603021, 0x3c010001, 
+0xac223514, 0xc0016be, 0x2203821, 0x3c040001, 0x248426ec, 0x21900, 
 0x31982, 0x3c050800, 0x651825, 0xae430078, 0x96e60462, 0x24050012, 
-0x3c010001, 0xac2233bc, 0x1000000a, 0x3821, 0x34423000, 0x240a0001, 
-0x3c040001, 0x248425c8, 0x3405f001, 0x3021, 0x3821, 0xa3aa0047, 
-0xafa20020, 0xafa00010, 0xc0028eb, 0xafa00014, 0x10000015, 0x0, 
-0x3c040001, 0x2484960c, 0x3c050001, 0x24a59814, 0xa42823, 0x2603021, 
-0x27b10034, 0xc0016be, 0x2203821, 0x3c040001, 0x2484c4ec, 0x3c050001, 
-0x24a5cf24, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, 
-0x3c010001, 0xac2233b4, 0x3c020001, 0x8c4233b4, 0x3c030800, 0x21100, 
+0x3c010001, 0xac22351c, 0x1000000a, 0x3821, 0x34423000, 0x240a0001, 
+0x3c040001, 0x248426f8, 0x3405f001, 0x3021, 0x3821, 0xa3aa0047, 
+0xafa20020, 0xafa00010, 0xc00290f, 0xafa00014, 0x10000015, 0x0, 
+0x3c040001, 0x2484960c, 0x3c050001, 0x24a59808, 0xa42823, 0x2603021, 
+0x27b10034, 0xc0016be, 0x2203821, 0x3c040001, 0x2484c57c, 0x3c050001, 
+0x24a5d050, 0xa42823, 0x2603021, 0x2203821, 0xc0016be, 0xaec200a8, 
+0x3c010001, 0xac223514, 0x3c020001, 0x8c423514, 0x3c030800, 0x21100, 
 0x21182, 0x431025, 0xae420038, 0x8f420218, 0x30420040, 0x14400004, 
 0x24020001, 0x3c010001, 0x370821, 0xa02281ec, 0x96e20462, 0x30420010, 
 0x14400009, 0x0, 0x96e20472, 0x30420010, 0x10400021, 0x0, 
 0x96e20462, 0x30420010, 0x10400005, 0x3c020700, 0x96e20472, 0x30420010, 
 0x14400011, 0x3c020700, 0x34423000, 0x240a0001, 0xa3aa0047, 0xafa20020, 
 0x8ee20154, 0x96e60462, 0x96e70472, 0x24420001, 0xaee20154, 0x8ee20154, 
-0x3c040001, 0x248425d4, 0x3405f002, 0xafa00010, 0xc0028eb, 0xafa00014, 
-0x96e60472, 0x96e70462, 0x3c040001, 0x248425dc, 0x24050012, 0xafa00010, 
-0xc0028eb, 0xafa00014, 0x3c040001, 0x2484d65c, 0x3c050001, 0x24a5d818, 
+0x3c040001, 0x24842704, 0x3405f002, 0xafa00010, 0xc00290f, 0xafa00014, 
+0x96e60472, 0x96e70462, 0x3c040001, 0x2484270c, 0x24050012, 0xafa00010, 
+0xc00290f, 0xafa00014, 0x3c040001, 0x2484d788, 0x3c050001, 0x24a5d944, 
 0xa42823, 0x27b30030, 0x2603021, 0x27b10034, 0xc0016be, 0x2203821, 
-0x3c1e0fff, 0x37deffff, 0x3c040001, 0x2484d820, 0x3c050001, 0x24a5d9dc, 
-0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2233a8, 0x5e1024, 
+0x3c1e0fff, 0x37deffff, 0x3c040001, 0x2484d94c, 0x3c050001, 0x24a5db08, 
+0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac223508, 0x5e1024, 
 0x21082, 0x3c150800, 0x551025, 0xc0016be, 0xae420050, 0x3c040000, 
 0x24847d00, 0x3c050000, 0x24a57f50, 0xa42823, 0x2603021, 0x2203821, 
-0x3c010001, 0xac2233c0, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 
+0x3c010001, 0xac223520, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 
 0xae420048, 0x3c040000, 0x24846134, 0x3c050000, 0x24a56244, 0xa42823, 
-0x2603021, 0x2203821, 0x3c010001, 0xac223388, 0x5e1024, 0x21082, 
+0x2603021, 0x2203821, 0x3c010001, 0xac2234e8, 0x5e1024, 0x21082, 
 0x551025, 0xc0016be, 0xae4200b8, 0x3c040000, 0x2484624c, 0x3c050000, 
-0x24a5631c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac22337c, 
+0x24a5631c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2234dc, 
 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200e8, 0x3c040000, 
 0x24846324, 0x3c050000, 0x24a565a4, 0xa42823, 0x2603021, 0x2203821, 
-0x3c010001, 0xac22336c, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 
+0x3c010001, 0xac2234cc, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 
 0xae4200f0, 0x3c040000, 0x248465ac, 0x3c050000, 0x24a566e0, 0xa42823, 
-0x2603021, 0x2203821, 0x3c010001, 0xac223374, 0x5e1024, 0x21082, 
-0x551025, 0xc0016be, 0xae4200c0, 0x3c040001, 0x2484e3dc, 0x3c050001, 
-0x24a5e98c, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac223380, 
+0x2603021, 0x2203821, 0x3c010001, 0xac2234d4, 0x5e1024, 0x21082, 
+0x551025, 0xc0016be, 0xae4200c0, 0x3c040001, 0x2484e50c, 0x3c050001, 
+0x24a5eabc, 0xa42823, 0x2603021, 0x2203821, 0x3c010001, 0xac2234e0, 
 0x5e1024, 0x21082, 0x551025, 0xc0016be, 0xae4200c8, 0x3c040001, 
-0x2484ed00, 0x3c050001, 0x24a5edd8, 0xa42823, 0x2603021, 0x2203821, 
-0x3c010001, 0xac2233c4, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 
-0xae4200d0, 0x3c040001, 0x8c8433b8, 0x3c050001, 0x8ca533a4, 0x2603021, 
-0x2203821, 0xc0016be, 0xaec200ac, 0x3c040001, 0x8c8433b0, 0x3c050001, 
-0x8ca533ac, 0x2603021, 0x3c010001, 0xac2233b8, 0xc0016be, 0x2203821, 
-0x3c010001, 0xac2233b0, 0x3c070001, 0xf73821, 0x90e781ec, 0xafa00010, 
-0x8fa20034, 0xafa20014, 0x8fa60030, 0x3c040001, 0x248425e8, 0xc0028eb, 
-0x2821, 0x8faa003c, 0xc003beb, 0x1408021, 0xc0038a8, 0x0, 
+0x2484ee30, 0x3c050001, 0x24a5ef08, 0xa42823, 0x2603021, 0x2203821, 
+0x3c010001, 0xac223524, 0x5e1024, 0x21082, 0x551025, 0xc0016be, 
+0xae4200d0, 0x3c040001, 0x8c843518, 0x3c050001, 0x8ca53504, 0x2603021, 
+0x2203821, 0xc0016be, 0xaec200ac, 0x3c040001, 0x8c843510, 0x3c050001, 
+0x8ca5350c, 0x2603021, 0x3c010001, 0xac223518, 0xc0016be, 0x2203821, 
+0x3c010001, 0xac223510, 0x3c070001, 0xf73821, 0x90e781ec, 0xafa00010, 
+0x8fa20034, 0xafa20014, 0x8fa60030, 0x3c040001, 0x24842718, 0xc00290f, 
+0x2821, 0x8faa003c, 0xc003c37, 0x1408021, 0xc0038f4, 0x0, 
 0xc002548, 0x0, 0xaec0002c, 0xaf400228, 0xaf40022c, 0xaee004a8, 
 0xaec00014, 0xaec00018, 0xaec00024, 0x96e20450, 0x2442ffff, 0xaec20028, 
 0x3c010001, 0x370821, 0xac2081d4, 0xaec00038, 0xaec00044, 0xaec0003c, 
@@ -3141,55 +3163,55 @@
 0xa2c00115, 0x3c1433d8, 0x3694c348, 0x3c020800, 0x34420080, 0x3c040000, 
 0x248459dc, 0x3c050000, 0x24a55a08, 0xa42823, 0x2603021, 0x2203821, 
 0xaf820060, 0x2402ffff, 0xaec00030, 0xaec00034, 0xc0016be, 0xaf820064, 
-0x3c010001, 0xac223364, 0x5e1024, 0x21082, 0x551025, 0xc00181c, 
+0x3c010001, 0xac2234c4, 0x5e1024, 0x21082, 0x551025, 0xc00181c, 
 0xae420000, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 0x3c020000, 
 0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 0x551024, 0x14400005, 
-0x3c030800, 0x8f820060, 0x431024, 0x1040fffd, 0x0, 0xc0038b5, 
+0x3c030800, 0x8f820060, 0x431024, 0x1040fffd, 0x0, 0xc003901, 
 0x0, 0x3c020100, 0xafa20028, 0x8ec3002c, 0x240200ff, 0x10620003, 
 0x8821, 0x8ec2002c, 0x24510001, 0x8f420228, 0x1622000f, 0x24070008, 
-0x3c040001, 0x248424fc, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
-0x3c050009, 0xc0028eb, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 
+0x3c040001, 0x2484262c, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
+0x3c050009, 0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 
 0x10000046, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8fa30028, 
 0x8fa4002c, 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 
 0x8ec6002c, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 
 0x604821, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x832021, 
 0x630c0, 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 
-0x5440000c, 0xaed1002c, 0x3c040001, 0x24842508, 0xafa00010, 0xafa00014, 
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 
+0x5440000c, 0xaed1002c, 0x3c040001, 0x24842638, 0xafa00010, 0xafa00014, 
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 
 0x0, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 
 0x24020011, 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 
-0x40f809, 0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842510, 
-0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 
+0x40f809, 0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842640, 
+0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 
 0x34a5f001, 0x8ec202a4, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x8ec20248, 
 0x24420001, 0xaec20248, 0x8ec20248, 0x93a20047, 0x10400070, 0x240200ff, 
 0x8ec3002c, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001, 
-0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 0x248424fc, 
-0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 
+0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 0x2484262c, 
+0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 
 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 0x8ec202a0, 
 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 
 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 
 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 0x604821, 
 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 0xafa20018, 
 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, 0xaed1002c, 
-0x3c040001, 0x24842508, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
-0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488, 
+0x3c040001, 0x24842638, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
+0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0, 0x8ee40488, 
 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 0xafa20010, 
 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 
-0x1440000e, 0x0, 0x3c040001, 0x24842510, 0xafa00010, 0xafa00014, 
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, 0x8ec202a4, 
-0x24420001, 0xaec202a4, 0x8ec202a4, 0x3c040001, 0x248425f4, 0x8ec20254, 
+0x1440000e, 0x0, 0x3c040001, 0x24842640, 0xafa00010, 0xafa00014, 
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 0x8ec202a4, 
+0x24420001, 0xaec202a4, 0x8ec202a4, 0x3c040001, 0x24842724, 0x8ec20254, 
 0x3c050009, 0x34a59999, 0x24420001, 0xaec20254, 0x8ec20254, 0x3021, 
-0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x10000004, 0x0, 
+0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x10000004, 0x0, 
 0x8f420264, 0x10400005, 0x0, 0x8f8200a0, 0x30420004, 0x1440fffa, 
 0x0, 0x8f820044, 0x34420004, 0xaf820044, 0x8ec2026c, 0x24420001, 
 0xaec2026c, 0x8ec2026c, 0x8f8200d8, 0x8f8300d4, 0x431023, 0x2442fff8, 
 0xaec20088, 0x8ec20088, 0x4410006, 0x24020001, 0x8ec20088, 0x8ec3053c, 
 0x431021, 0xaec20088, 0x24020001, 0xaec20070, 0x96e20452, 0x30420010, 
 0x10400005, 0x0, 0x8f820214, 0x3c038100, 0x431025, 0xaf820214, 
-0x3c020001, 0x8c4232a8, 0x30420001, 0x10400007, 0x0, 0x3c040000, 
+0x3c020001, 0x8c423408, 0x30420001, 0x10400007, 0x0, 0x3c040000, 
 0x24846bb4, 0x3c050000, 0x24a570e8, 0x10000006, 0xa42823, 0x3c040000, 
 0x248466e8, 0x3c050000, 0x24a56bac, 0xa42823, 0x27a60030, 0xc0016be, 
-0x27a70034, 0x3c010001, 0xac223378, 0x3c020001, 0x8c423378, 0x3c030800, 
+0x27a70034, 0x3c010001, 0xac2234d8, 0x3c020001, 0x8c4234d8, 0x3c030800, 
 0x21100, 0x21182, 0x431025, 0xae420040, 0x8f830060, 0x74100b, 
 0x242000a, 0x200f821, 0x0, 0xd, 0x8fbf0060, 0x8fbe005c, 
 0x8fb50058, 0x8fb30054, 0x8fb10050, 0x3e00008, 0x27bd0068, 0x3e00008, 
@@ -3199,69 +3221,69 @@
 0x27bdfde0, 0x27a70018, 0x3c02dead, 0x3442beef, 0xafbf0218, 0x8f830150, 
 0x3c04001f, 0x3484ffff, 0xafa20018, 0xe33823, 0xe43824, 0x8ce30000, 
 0x10620008, 0x0, 0xafa30010, 0xafa00014, 0x8f860150, 0x3c040001, 
-0x24842600, 0xc0028eb, 0x24050020, 0x8fbf0218, 0x3e00008, 0x27bd0220, 
+0x24842730, 0xc00290f, 0x24050020, 0x8fbf0218, 0x3e00008, 0x27bd0220, 
 0x27bdffe0, 0x3c06abba, 0x34c6babe, 0xafb10018, 0x3c110004, 0x3c07007f, 
 0x34e7ffff, 0xafbf001c, 0x112840, 0x8e240000, 0x8ca30000, 0xaca00000, 
 0xae260000, 0x8ca20000, 0xaca30000, 0x10460005, 0xae240000, 0xa08821, 
-0xf1102b, 0x1040fff5, 0x112840, 0x3c040001, 0x2484260c, 0x2202821, 
-0x3021, 0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x2201021, 
+0xf1102b, 0x1040fff5, 0x112840, 0x3c040001, 0x2484273c, 0x2202821, 
+0x3021, 0x3821, 0xafa00010, 0xc00290f, 0xafa00014, 0x2201021, 
 0x8fbf001c, 0x8fb10018, 0x3e00008, 0x27bd0020, 0x27bdffc8, 0xafb30024, 
 0x809821, 0xafbe002c, 0xafb50028, 0xe0a821, 0x24a50003, 0xafbf0030, 
 0xafb10020, 0x8ea20000, 0x2403fffc, 0xa38824, 0x51102b, 0x14400020, 
 0xc0f021, 0x8fc80000, 0xafa00010, 0xafa8001c, 0x8ea20000, 0x3c040001, 
-0x24842618, 0xafa20014, 0x8fc60000, 0x2602821, 0xc0028eb, 0x2203821, 
+0x24842748, 0xafa20014, 0x8fc60000, 0x2602821, 0xc00290f, 0x2203821, 
 0x8fc60000, 0x111882, 0x2463ffff, 0x2402ffff, 0x10620008, 0x2602021, 
 0x2405ffff, 0x8c820000, 0x24840004, 0x2463ffff, 0xacc20000, 0x1465fffb, 
 0x24c60004, 0x8ea20000, 0x511023, 0xaea20000, 0x8fc20000, 0x511021, 
-0x1000000b, 0xafc20000, 0xafa00010, 0x8ea20000, 0x3c040001, 0x24842620, 
-0xafa20014, 0x8fc60000, 0x2602821, 0x2203821, 0xc0028eb, 0xafa5001c, 
+0x1000000b, 0xafc20000, 0xafa00010, 0x8ea20000, 0x3c040001, 0x24842750, 
+0xafa20014, 0x8fc60000, 0x2602821, 0x2203821, 0xc00290f, 0xafa5001c, 
 0x8fa2001c, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020, 
 0x3e00008, 0x27bd0038, 0x27bdffe8, 0x3c1cc000, 0xd021, 0x3c05ffff, 
-0x3c030001, 0x8c633340, 0x3c040001, 0x8c843348, 0x34a57e10, 0x24021ffc, 
-0x3c010001, 0xac2231e0, 0x3c0200c0, 0x3c010001, 0xac2231e4, 0x3c020020, 
+0x3c030001, 0x8c6334a0, 0x3c040001, 0x8c8434a8, 0x34a57e10, 0x24021ffc, 
+0x3c010001, 0xac223340, 0x3c0200c0, 0x3c010001, 0xac223344, 0x3c020020, 
 0xafbf0010, 0x3c0100c0, 0xac201ffc, 0x431023, 0x441023, 0x245bb000, 
-0x365b821, 0x3c1d0001, 0x8fbd31dc, 0x3a0f021, 0x3c0400c0, 0x34840200, 
-0x3c1600c0, 0x3c0300c0, 0x34630758, 0x24021dfc, 0x3c010001, 0xac2231e0, 
-0x240218a4, 0x3c010001, 0xac2431e4, 0x3c010001, 0xac2231e0, 0x3c010001, 
-0xac2331e4, 0xc00172c, 0x36d60200, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
-0x27bdffc8, 0x3c040001, 0x24842628, 0x2821, 0x3c020001, 0x8c4231e0, 
-0x3c030001, 0x8c6331e4, 0x3021, 0x3603821, 0xafbf0030, 0xafbe002c, 
+0x365b821, 0x3c1d0001, 0x8fbd333c, 0x3a0f021, 0x3c0400c0, 0x34840200, 
+0x3c1600c0, 0x3c0300c0, 0x34630758, 0x24021dfc, 0x3c010001, 0xac223340, 
+0x240218a4, 0x3c010001, 0xac243344, 0x3c010001, 0xac223340, 0x3c010001, 
+0xac233344, 0xc00172c, 0x36d60200, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
+0x27bdffc8, 0x3c040001, 0x24842758, 0x2821, 0x3c020001, 0x8c423340, 
+0x3c030001, 0x8c633344, 0x3021, 0x3603821, 0xafbf0030, 0xafbe002c, 
 0xafb50028, 0xafb30024, 0xafb10020, 0xafa2001c, 0xafa30018, 0xafb70010, 
-0xc0028eb, 0xafb60014, 0xc001849, 0x0, 0x8f820240, 0x34420004, 
+0xc00290f, 0xafb60014, 0xc001849, 0x0, 0x8f820240, 0x34420004, 
 0xaf820240, 0x24020001, 0xaec20000, 0x3c020001, 0x571021, 0x904281ec, 
-0x10400090, 0x2402fffc, 0x3c110001, 0x2631a33b, 0x3c150001, 0x26b59ee8, 
+0x10400090, 0x2402fffc, 0x3c110001, 0x2631a3c3, 0x3c150001, 0x26b59f70, 
 0x2351823, 0x8fa6001c, 0x628824, 0xd1102b, 0x1440001e, 0x27be0018, 
-0x8fb30018, 0x3c040001, 0x24842618, 0x2a02821, 0x2203821, 0xafa00010, 
-0xafa60014, 0xc0028eb, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 
+0x8fb30018, 0x3c040001, 0x24842748, 0x2a02821, 0x2203821, 0xafa00010, 
+0xafa60014, 0xc00290f, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 
 0x2402ffff, 0x10620008, 0x2a02821, 0x2406ffff, 0x8ca20000, 0x24a50004, 
 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x511023, 
 0xafa2001c, 0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 
-0x24842620, 0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 
-0xc0028eb, 0xa09821, 0x8fa3001c, 0x24150020, 0x3c010001, 0xac33335c, 
-0x2c620020, 0x1440001d, 0x27b30018, 0x8fb10018, 0x3c040001, 0x24842618, 
-0x3c050001, 0x24a533f0, 0x24070020, 0xafa00010, 0xafa30014, 0xc0028eb, 
-0x2203021, 0x3c050001, 0x24a533f0, 0x8fa40018, 0x24030007, 0x2406ffff, 
+0x24842750, 0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 
+0xc00290f, 0xa09821, 0x8fa3001c, 0x24150020, 0x3c010001, 0xac3334bc, 
+0x2c620020, 0x1440001d, 0x27b30018, 0x8fb10018, 0x3c040001, 0x24842748, 
+0x3c050001, 0x24a53550, 0x24070020, 0xafa00010, 0xafa30014, 0xc00290f, 
+0x2203021, 0x3c050001, 0x24a53550, 0x8fa40018, 0x24030007, 0x2406ffff, 
 0x8ca20000, 0x24a50004, 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 
 0x8fa2001c, 0x551023, 0xafa2001c, 0x8e620000, 0x551021, 0x1000000c, 
-0xae620000, 0x3c040001, 0x24842620, 0x3c050001, 0x24a533f0, 0xafa00010, 
-0xafa30014, 0x8fa60018, 0x3c110001, 0x263133f0, 0xc0028eb, 0x24070020, 
-0x8fa3001c, 0x24150020, 0x3c010001, 0xac313390, 0x2c620020, 0x1440001d, 
-0x27b30018, 0x8fb10018, 0x3c040001, 0x24842618, 0x3c050001, 0x24a53410, 
-0x24070020, 0xafa00010, 0xafa30014, 0xc0028eb, 0x2203021, 0x3c050001, 
-0x24a53410, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004, 
+0xae620000, 0x3c040001, 0x24842750, 0x3c050001, 0x24a53550, 0xafa00010, 
+0xafa30014, 0x8fa60018, 0x3c110001, 0x26313550, 0xc00290f, 0x24070020, 
+0x8fa3001c, 0x24150020, 0x3c010001, 0xac3134f0, 0x2c620020, 0x1440001d, 
+0x27b30018, 0x8fb10018, 0x3c040001, 0x24842748, 0x3c050001, 0x24a53570, 
+0x24070020, 0xafa00010, 0xafa30014, 0xc00290f, 0x2203021, 0x3c050001, 
+0x24a53570, 0x8fa40018, 0x24030007, 0x2406ffff, 0x8ca20000, 0x24a50004, 
 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x551023, 
 0xafa2001c, 0x8e620000, 0x551021, 0x1000000c, 0xae620000, 0x3c040001, 
-0x24842620, 0x3c050001, 0x24a53410, 0xafa00010, 0xafa30014, 0x8fa60018, 
-0x3c110001, 0x26313410, 0xc0028eb, 0x24070020, 0x3c010001, 0x10000033, 
-0xac31338c, 0x3c110000, 0x26317cef, 0x3c150000, 0x26b57b3c, 0x2351823, 
+0x24842750, 0x3c050001, 0x24a53570, 0xafa00010, 0xafa30014, 0x8fa60018, 
+0x3c110001, 0x26313570, 0xc00290f, 0x24070020, 0x3c010001, 0x10000033, 
+0xac3134ec, 0x3c110000, 0x26317cef, 0x3c150000, 0x26b57b3c, 0x2351823, 
 0x8fa6001c, 0x628824, 0xd1102b, 0x1440001e, 0x27be0018, 0x8fb30018, 
-0x3c040001, 0x24842618, 0x2a02821, 0x2203821, 0xafa00010, 0xafa60014, 
-0xc0028eb, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff, 
+0x3c040001, 0x24842748, 0x2a02821, 0x2203821, 0xafa00010, 0xafa60014, 
+0xc00290f, 0x2603021, 0x8fa40018, 0x111882, 0x2463ffff, 0x2402ffff, 
 0x10620008, 0x2a02821, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 
 0xac820000, 0x1466fffb, 0x24840004, 0x8fa2001c, 0x511023, 0xafa2001c, 
-0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 0x24842620, 
-0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 0xc0028eb, 
-0xa09821, 0x3c010001, 0xac33335c, 0x3c030001, 0x8c63335c, 0x24020400, 
+0x8fc20000, 0x511021, 0x1000000a, 0xafc20000, 0x3c040001, 0x24842750, 
+0x2a02821, 0xafa00010, 0xafa60014, 0x8fa60018, 0x2203821, 0xc00290f, 
+0xa09821, 0x3c010001, 0xac3334bc, 0x3c030001, 0x8c6334bc, 0x24020400, 
 0x60f809, 0xaf820070, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 
 0x8fb10020, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x0, 
 0x8f820040, 0x3c03f000, 0x431824, 0x3c025000, 0x10620005, 0x3c026000, 
@@ -3272,13 +3294,13 @@
 0x8f820054, 0x244203e8, 0xaf820058, 0x240201f4, 0xaec200c8, 0x24020004, 
 0xaec200d0, 0x24020002, 0xaec000a0, 0xaec000cc, 0xaec200c4, 0xaec000c0, 
 0xaec000bc, 0x3e00008, 0xaec000b8, 0x8f820054, 0x24420005, 0x3e00008, 
-0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x3c030001, 0x8c6332bc, 
-0x244203e8, 0x1060001d, 0xaf820058, 0x3c020001, 0x8c4232a8, 0x30420001, 
-0x1440000c, 0x0, 0x3c020001, 0x8c4233c8, 0x10400008, 0x0, 
-0x8f830224, 0x3c020001, 0x8c42548c, 0x10620003, 0x0, 0xc003a65, 
+0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x3c030001, 0x8c63341c, 
+0x244203e8, 0x1060001d, 0xaf820058, 0x3c020001, 0x8c423408, 0x30420001, 
+0x1440000c, 0x0, 0x3c020001, 0x8c423528, 0x10400008, 0x0, 
+0x8f830224, 0x3c020001, 0x8c4255ec, 0x10620003, 0x0, 0xc003ab1, 
 0x0, 0x92c200ec, 0x10400003, 0x3c0208ff, 0x1000000a, 0xa2c000ec, 
 0x3442fffb, 0x8f830220, 0x3c040200, 0x284a025, 0x621824, 0x10000003, 
-0xaf830220, 0xc003d6d, 0x0, 0x8f420238, 0x1040000a, 0x0, 
+0xaf830220, 0xc003db9, 0x0, 0x8f420238, 0x1040000a, 0x0, 
 0x8ec200a0, 0x244203e8, 0xaec200a0, 0x8f430238, 0x43102b, 0x14400003, 
 0x0, 0xc001c3c, 0x0, 0x8f420218, 0x30420100, 0x10400003, 
 0x0, 0xc001e07, 0x0, 0x8ec200c0, 0x8ec300c4, 0x24420001, 
@@ -3297,14 +3319,14 @@
 0x3c020001, 0x571021, 0x8c4281d4, 0x10400023, 0x24070008, 0x8ed10018, 
 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 
 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 
-0x24020001, 0x3c040001, 0x24842690, 0xafb10010, 0xafa00014, 0x8ec6002c, 
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 
+0x24020001, 0x3c040001, 0x248427c0, 0xafb10010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 
 0x24020001, 0x3c010001, 0x370821, 0x1000005c, 0xac2281d4, 0x3c010001, 
 0x370821, 0x10000022, 0xac2081d0, 0x8ed10018, 0x8ee40498, 0x8ee5049c, 
 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 
 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 
-0x24842690, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
-0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 
+0x248427c0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
+0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 
 0x370821, 0x1000003a, 0xac2281d8, 0x3c010001, 0x370821, 0xac2281d0, 
 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4, 
 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 0x1000002a, 
@@ -3323,8 +3345,8 @@
 0xafbf0024, 0xafb10020, 0x8ec30068, 0x8ec2006c, 0x10620029, 0x24070008, 
 0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, 
 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 
-0x1440000b, 0x24020001, 0x3c040001, 0x2484269c, 0xafb10010, 0xafa00014, 
-0x8ec60068, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f008, 0x1021, 
+0x1440000b, 0x24020001, 0x3c040001, 0x248427cc, 0xafb10010, 0xafa00014, 
+0x8ec60068, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, 
 0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000000e, 0xac2281e0, 
 0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, 
 0x24420001, 0xaec20268, 0x10000004, 0x8ec20268, 0x3c010001, 0x370821, 
@@ -3333,15 +3355,15 @@
 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 0xaf820060, 
 0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 
-0x3c020001, 0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 
+0x3c020001, 0x8c42341c, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 
 0xafb3002c, 0x104000fe, 0xafb10028, 0x8ec200b8, 0x24430001, 0x2842000b, 
 0x1440011b, 0xaec300b8, 0xaec000b8, 0x8ee204a8, 0x30420002, 0x14400096, 
-0x0, 0x8ee204a8, 0x3c030001, 0x8c6332ac, 0x34420002, 0xaee204a8, 
+0x0, 0x8ee204a8, 0x3c030001, 0x8c63340c, 0x34420002, 0xaee204a8, 
 0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 
 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 
 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 0x0, 
-0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
-0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 
+0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
+0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 
 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 
 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 
 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000c, 0x8ec8002c, 
@@ -3350,7 +3372,7 @@
 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 
 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 
 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 
-0x3c040001, 0x248426d4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
+0x3c040001, 0x24842804, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 
 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054, 0x8f820054, 
 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 0xa821, 0x3c1e0020, 
@@ -3358,8 +3380,8 @@
 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8, 0x24070008, 
 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054, 0x2221023, 
 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 0x1440000f, 0x0, 
-0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
-0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 
+0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
+0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 
 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250, 0x8ec20250, 
 0x8ee204a8, 0x30420001, 0x10400054, 0x0, 0x8f420218, 0x30420080, 
 0x1040002b, 0x0, 0x8f820044, 0x34420040, 0xaf820044, 0x8ec200b0, 
@@ -3384,15 +3406,15 @@
 0x24430001, 0x284201f5, 0x14400005, 0xaec300bc, 0x8f820044, 0x38420020, 
 0xaf820044, 0xaec000bc, 0x2402ff7f, 0x282a024, 0x8fbf0038, 0x8fbe0034, 
 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3e00008, 
-0x0, 0x3c020001, 0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 
+0x0, 0x3c020001, 0x8c42341c, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 
 0xafb50030, 0xafb3002c, 0x10400100, 0xafb10028, 0x8ec200b8, 0x3c040001, 
-0x8c8432ac, 0x24430001, 0x2842000b, 0xaec400d0, 0x14400127, 0xaec300b8, 
+0x8c84340c, 0x24430001, 0x2842000b, 0xaec400d0, 0x14400127, 0xaec300b8, 
 0xaec000b8, 0x8ee204a8, 0x30420002, 0x14400094, 0x0, 0x8ee204a8, 
 0x34420002, 0xaee204a8, 0x24020001, 0x14820003, 0x3c020600, 0x10000002, 
 0x34423000, 0x34421000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 
 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 
-0x1662000f, 0x0, 0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, 
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 
+0x1662000f, 0x0, 0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, 
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 
 0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 
 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 
 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 
@@ -3401,7 +3423,7 @@
 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 
 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 
 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 
-0x54400011, 0xaed3002c, 0x3c040001, 0x248426d4, 0xafa00010, 0xafa00014, 
+0x54400011, 0xaed3002c, 0x3c040001, 0x24842804, 0xafa00010, 0xafa00014, 
 0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 
 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 
 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 
@@ -3409,35 +3431,35 @@
 0x8ec3002c, 0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 
 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 
 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 
-0x1440000f, 0x0, 0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, 
-0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, 
+0x1440000f, 0x0, 0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, 
+0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 
 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 
 0xaec20250, 0x8ec20250, 0x8ee204a8, 0x30420001, 0x10400055, 0x0, 
 0x8f420218, 0x30420080, 0x10400027, 0x0, 0x8ec200b0, 0x3c040001, 
-0x90843370, 0x24080000, 0x2409ffff, 0x403821, 0x8ec201b8, 0x8ec301bc, 
-0x3021, 0x34840020, 0x3c010001, 0xa0243370, 0x481024, 0x1446000d, 
+0x908434d0, 0x24080000, 0x2409ffff, 0x403821, 0x8ec201b8, 0x8ec301bc, 
+0x3021, 0x34840020, 0x3c010001, 0xa02434d0, 0x481024, 0x1446000d, 
 0x691824, 0x1467000b, 0x0, 0x8ec200b4, 0x403821, 0x8ec201d8, 
 0x8ec301dc, 0x3021, 0x481024, 0x14460003, 0x691824, 0x10670009, 
-0x308200bf, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 0x90843370, 0x8ec601d8, 
-0x8ec701dc, 0x10000026, 0x38840040, 0x3c010001, 0x10000061, 0xa0223370, 
-0x8ec200b0, 0x3c040001, 0x90843370, 0x24080000, 0x2409ffff, 0x403821, 
-0x8ec201b8, 0x8ec301bc, 0x3021, 0x308400bf, 0x3c010001, 0xa0243370, 
+0x308200bf, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 0x908434d0, 0x8ec601d8, 
+0x8ec701dc, 0x10000026, 0x38840040, 0x3c010001, 0x10000061, 0xa02234d0, 
+0x8ec200b0, 0x3c040001, 0x908434d0, 0x24080000, 0x2409ffff, 0x403821, 
+0x8ec201b8, 0x8ec301bc, 0x3021, 0x308400bf, 0x3c010001, 0xa02434d0, 
 0x481024, 0x1446000d, 0x691824, 0x1467000b, 0x0, 0x8ec200b4, 
 0x403821, 0x8ec201d8, 0x8ec301dc, 0x3021, 0x481024, 0x14460003, 
 0x691824, 0x1067000d, 0x34820020, 0x8ec201b8, 0x8ec301bc, 0x3c040001, 
-0x90843370, 0x8ec601d8, 0x8ec701dc, 0x38840020, 0xaec300b0, 0xaec700b4, 
-0x3c010001, 0x1000003a, 0xa0243370, 0x3c010001, 0x10000037, 0xa0223370, 
-0x3c020001, 0x90423370, 0x8ec300bc, 0x34440020, 0x24620001, 0x10000028, 
+0x908434d0, 0x8ec601d8, 0x8ec701dc, 0x38840020, 0xaec300b0, 0xaec700b4, 
+0x3c010001, 0x1000003a, 0xa02434d0, 0x3c010001, 0x10000037, 0xa02234d0, 
+0x3c020001, 0x904234d0, 0x8ec300bc, 0x34440020, 0x24620001, 0x10000028, 
 0x28630033, 0x8ec200cc, 0x8ec300c8, 0x24420001, 0xaec200cc, 0x43102a, 
 0x14400006, 0x24030001, 0x8ec200d0, 0x14430002, 0xaec000cc, 0x24030004, 
 0xaec300d0, 0x8ee204a8, 0x30420001, 0x10400012, 0x0, 0x8f420218, 
-0x30420080, 0x10400008, 0x0, 0x3c020001, 0x90423370, 0x34420040, 
-0x304200df, 0x3c010001, 0x10000015, 0xa0223370, 0x3c020001, 0x90423370, 
-0x34420060, 0x3c010001, 0x1000000f, 0xa0223370, 0x3c020001, 0x90423370, 
-0x8ec300bc, 0x34440020, 0x24620001, 0x286300fb, 0x3c010001, 0xa0243370, 
-0x14600005, 0xaec200bc, 0x38820040, 0x3c010001, 0xa0223370, 0xaec000bc, 
-0x3c020001, 0x90423370, 0x8ec300d0, 0x3044007f, 0x24020001, 0x3c010001, 
-0xa0243370, 0x54620003, 0x3484000f, 0x42102, 0x348400f0, 0xc004904, 
+0x30420080, 0x10400008, 0x0, 0x3c020001, 0x904234d0, 0x34420040, 
+0x304200df, 0x3c010001, 0x10000015, 0xa02234d0, 0x3c020001, 0x904234d0, 
+0x34420060, 0x3c010001, 0x1000000f, 0xa02234d0, 0x3c020001, 0x904234d0, 
+0x8ec300bc, 0x34440020, 0x24620001, 0x286300fb, 0x3c010001, 0xa02434d0, 
+0x14600005, 0xaec200bc, 0x38820040, 0x3c010001, 0xa02234d0, 0xaec000bc, 
+0x3c020001, 0x904234d0, 0x8ec300d0, 0x3044007f, 0x24020001, 0x3c010001, 
+0xa02434d0, 0x54620003, 0x3484000f, 0x42102, 0x348400f0, 0xc004950, 
 0x0, 0x2402ff7f, 0x282a024, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 
 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3e00008, 0x0, 
 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0xafb10028, 
@@ -3477,7 +3499,7 @@
 0x8ec200a8, 0x26e60028, 0x40f809, 0x24070400, 0x104000f1, 0x3c020400, 
 0xafa20020, 0x92c20115, 0x10400080, 0x240200ff, 0x8ec3002c, 0x10620004, 
 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 
-0x1662000a, 0x0, 0x3c040001, 0x248426c8, 0xafa00010, 0xafa00014, 
+0x1662000a, 0x0, 0x3c040001, 0x248427f8, 0xafa00010, 0xafa00014, 
 0x8ec6002c, 0x8f470228, 0x3c050009, 0x1000007f, 0x34a5f00f, 0x8ec2002c, 
 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 
 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 
@@ -3486,8 +3508,8 @@
 0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 
 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 
 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 
-0x32a200ff, 0x54400018, 0xaed3002c, 0x3c040001, 0x248426d4, 0xafa00010, 
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f010, 0xc0028eb, 
+0x32a200ff, 0x54400018, 0xaed3002c, 0x3c040001, 0x24842804, 0xafa00010, 
+0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f010, 0xc00290f, 
 0x0, 0x8ec202d0, 0x1821, 0x24420001, 0xaec202d0, 0x1000008f, 
 0x8ec202d0, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 
 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 
@@ -3495,23 +3517,23 @@
 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018, 
 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0, 
 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff, 
-0x1440006a, 0x24030001, 0x3c040001, 0x248426e0, 0xafa00010, 0xafa00014, 
+0x1440006a, 0x24030001, 0x3c040001, 0x24842810, 0xafa00010, 0xafa00014, 
 0x8f860120, 0x8f870124, 0x3c050009, 0x1000ffcb, 0x34a5f011, 0x8ec3002c, 
 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24510001, 0x8821, 
-0x8f420228, 0x16220011, 0x4021, 0x3c040001, 0x248426a8, 0xafa00010, 
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc0028eb, 
+0x8f420228, 0x16220011, 0x4021, 0x3c040001, 0x248427d8, 0xafa00010, 
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc00290f, 
 0x0, 0x8ec202a0, 0x1821, 0x24420001, 0xaec202a0, 0x10000047, 
 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 
 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 
 0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 
 0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 
 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, 
-0xaed1002c, 0x3c040001, 0x248426b4, 0xafa00010, 0xafa00014, 0x8ec6002c, 
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001e, 0x1821, 
+0xaed1002c, 0x3c040001, 0x248427e4, 0xafa00010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001e, 0x1821, 
 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 
 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, 
-0x24c6001c, 0x1440000f, 0x24030001, 0x3c040001, 0x248426bc, 0xafa00010, 
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, 
+0x24c6001c, 0x1440000f, 0x24030001, 0x3c040001, 0x248427ec, 0xafa00010, 
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 
 0x8ec202a4, 0x1821, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x1060000d, 
 0x24020001, 0x8ec2024c, 0xa2c00115, 0xaec000a0, 0x24420001, 0xaec2024c, 
 0x8ec2024c, 0x8ee2014c, 0x24420001, 0xaee2014c, 0x10000003, 0x8ee2014c, 
@@ -3524,15 +3546,15 @@
 0x8f8200b0, 0x2403fffb, 0x431024, 0xaf8200b0, 0x8f82011c, 0x2403fffd, 
 0x431024, 0x10000040, 0xaf82011c, 0x8ec30104, 0x8f820104, 0x14620005, 
 0x0, 0x8ec3010c, 0x8f8200b4, 0x5062000a, 0x3c050005, 0x8f820104, 
-0xaec20104, 0x8f8200b4, 0xaec2010c, 0x8ec2010c, 0x3c040001, 0x248426ec, 
-0x10000029, 0xafa00014, 0x8ec2010c, 0x3c040001, 0x248426f8, 0xafa00014, 
-0xafa20010, 0x8f8600b0, 0x8ec70104, 0xc0028eb, 0x34a50900, 0x8f82011c, 
+0xaec20104, 0x8f8200b4, 0xaec2010c, 0x8ec2010c, 0x3c040001, 0x2484281c, 
+0x10000029, 0xafa00014, 0x8ec2010c, 0x3c040001, 0x24842828, 0xafa00014, 
+0xafa20010, 0x8f8600b0, 0x8ec70104, 0xc00290f, 0x34a50900, 0x8f82011c, 
 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 
 0xaf830104, 0x8f440208, 0x8f45020c, 0x2402000f, 0xafa20010, 0xafa00014, 
 0x8ec20008, 0xafa20018, 0x8ec200a8, 0x26e60028, 0x40f809, 0x24070400, 
 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201cc, 0x24420001, 
-0xaee201cc, 0x8ee201cc, 0x8ec2010c, 0x3c040001, 0x24842704, 0xafa00014, 
-0xafa20010, 0x8f8600b0, 0x8ec70104, 0x3c050005, 0xc0028eb, 0x34a50900, 
+0xaee201cc, 0x8ee201cc, 0x8ec2010c, 0x3c040001, 0x24842834, 0xafa00014, 
+0xafa20010, 0x8f8600b0, 0x8ec70104, 0x3c050005, 0xc00290f, 0x34a50900, 
 0x8f8200a0, 0x30420004, 0x1040005f, 0x0, 0x8ec30108, 0x8f820124, 
 0x14620005, 0x0, 0x8ec30110, 0x8f8200a4, 0x10620006, 0x0, 
 0x8f820124, 0xaec20108, 0x8f8200a4, 0x10000052, 0xaec20110, 0x8f8200a0, 
@@ -3541,15 +3563,15 @@
 0x2403fffd, 0x431024, 0x10000041, 0xaf82011c, 0x8ec30108, 0x8f820124, 
 0x14620005, 0x0, 0x8ec30110, 0x8f8200a4, 0x5062000a, 0x3c050005, 
 0x8f820124, 0xaec20108, 0x8f8200a4, 0xaec20110, 0x8ec20110, 0x3c040001, 
-0x24842710, 0x1000002a, 0xafa00014, 0x8ec20110, 0x3c040001, 0x2484271c, 
-0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0xc0028eb, 0x34a50900, 
+0x24842840, 0x1000002a, 0xafa00014, 0x8ec20110, 0x3c040001, 0x2484284c, 
+0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0xc00290f, 0x34a50900, 
 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 
 0xaf8200a0, 0xaf830124, 0x8f440208, 0x8f45020c, 0x24020010, 0xafa20010, 
-0xafa00014, 0x8ec20010, 0xafa20018, 0x8ec200a4, 0x3c060001, 0x24c63384, 
+0xafa00014, 0x8ec20010, 0xafa20018, 0x8ec200a4, 0x3c060001, 0x24c634e4, 
 0x40f809, 0x24070004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 
 0x8ee201cc, 0x24420001, 0xaee201cc, 0x8ee201cc, 0x8ec20110, 0x3c040001, 
-0x24842728, 0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0x3c050005, 
-0xc0028eb, 0x34a50900, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c091000, 
+0x24842858, 0xafa00014, 0xafa20010, 0x8f8600a0, 0x8ec70108, 0x3c050005, 
+0xc00290f, 0x34a50900, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c091000, 
 0x24080001, 0x3c070080, 0x3c050100, 0x3c062000, 0x8f820070, 0x491024, 
 0x1040fffd, 0x0, 0x8f820054, 0x24420005, 0xaf820078, 0x8f420234, 
 0x10400017, 0x2021, 0x3c020001, 0x571021, 0x8c4281dc, 0x24420005, 
@@ -3576,7 +3598,7 @@
 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8ec20260, 0x24420001, 
 0xaec20260, 0x1000006f, 0x8ec20260, 0x30c20001, 0x10400004, 0x24020001, 
 0xaf820064, 0x10000069, 0x0, 0x30c20002, 0x1440000b, 0x3c050003, 
-0x3c040001, 0x24842800, 0x34a50001, 0x3821, 0xafa00010, 0xc0028eb, 
+0x3c040001, 0x24842930, 0x34a50001, 0x3821, 0xafa00010, 0xc00290f, 
 0xafa00014, 0x2402fff8, 0x1000005c, 0xaf820064, 0x8f43022c, 0x8f42010c, 
 0x1062004c, 0x0, 0x8f42022c, 0x21080, 0x5a1021, 0x8c440300, 
 0x8f42022c, 0x24420001, 0x3042003f, 0x41e02, 0xaf42022c, 0x24020003, 
@@ -3596,15 +3618,15 @@
 0x3e00008, 0x27bd0020, 0x3e00008, 0x0, 0x27bdffc0, 0xafb10028, 
 0x808821, 0x111602, 0x2442ffff, 0x304300ff, 0x2c620011, 0xafbf0038, 
 0xafbe0034, 0xafb50030, 0x104001ab, 0xafb3002c, 0x31080, 0x3c010001, 
-0x220821, 0x8c222848, 0x400008, 0x0, 0x111302, 0x30440fff, 
+0x220821, 0x8c222978, 0x400008, 0x0, 0x111302, 0x30440fff, 
 0x24020001, 0x10820006, 0x3c030800, 0x24020002, 0x1082000c, 0x3c050003, 
-0x10000022, 0x0, 0x3c020001, 0x8c4233b4, 0x21100, 0x21182, 
+0x10000022, 0x0, 0x3c020001, 0x8c423514, 0x21100, 0x21182, 
 0x431025, 0xae420038, 0x8ee204a8, 0x1000000a, 0x34420001, 0x3c020001, 
-0x2442c440, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8, 
+0x2442c4d0, 0x21100, 0x21182, 0x431025, 0xae420038, 0x8ee204a8, 
 0x2403fffe, 0x431024, 0xaee204a8, 0xaec40168, 0xaec4016c, 0x8f840054, 
 0x41442, 0x41c82, 0x431021, 0x41cc2, 0x431023, 0x41d02, 
 0x431021, 0x41d42, 0x431023, 0x10000009, 0xaec20170, 0x3c040001, 
-0x2484280c, 0x34a50004, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, 
+0x2484293c, 0x34a50004, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 
 0xafa00014, 0x8ec20208, 0x24420001, 0xaec20208, 0x100001e1, 0x8ec20208, 
 0xc0022fe, 0x0, 0x100001dd, 0x0, 0xc002419, 0x0, 
 0x100001d9, 0x0, 0x111302, 0x30430fff, 0x24020001, 0x10620005, 
@@ -3614,24 +3636,24 @@
 0xaf82022c, 0xaf820230, 0xaf820234, 0x24020001, 0x10000016, 0xa2c2011c, 
 0x92c2011c, 0x50400013, 0xa2c0011c, 0x8ee204ac, 0xaf820228, 0x8ee204b0, 
 0xaf82022c, 0x8ee204b4, 0xaf820230, 0x8ee204b8, 0xaf820234, 0x10000009, 
-0xa2c0011c, 0x3c040001, 0x24842818, 0x34a5f009, 0x2203021, 0x3821, 
-0xafa00010, 0xc0028eb, 0xafa00014, 0x8ec20234, 0x24420001, 0xaec20234, 
+0xa2c0011c, 0x3c040001, 0x24842948, 0x34a5f009, 0x2203021, 0x3821, 
+0xafa00010, 0xc00290f, 0xafa00014, 0x8ec20234, 0x24420001, 0xaec20234, 
 0x100001a3, 0x8ec20234, 0x111302, 0x30440fff, 0x24020001, 0x10820005, 
 0x24020002, 0x1082000d, 0x3c050003, 0x10000013, 0x0, 0x8f820220, 
 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24020001, 
 0xa2c2011d, 0x10000011, 0xaec40200, 0x8f820220, 0x3c0308ff, 0x3463fff7, 
 0x431024, 0xaf820220, 0xa2c0011d, 0x10000009, 0xaec40200, 0x3c040001, 
-0x24842824, 0x34a5f00a, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, 
+0x24842954, 0x34a5f00a, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 
 0xafa00014, 0x8ec20224, 0x24420001, 0xaec20224, 0x1000017b, 0x8ec20224, 
-0x27840208, 0x27450200, 0xc00297e, 0x24060008, 0x26c4018c, 0x27450200, 
-0xc00297e, 0x24060008, 0x8ec2022c, 0x24420001, 0xaec2022c, 0x1000016e, 
+0x27840208, 0x27450200, 0xc0029a2, 0x24060008, 0x26c4018c, 0x27450200, 
+0xc0029a2, 0x24060008, 0x8ec2022c, 0x24420001, 0xaec2022c, 0x1000016e, 
 0x8ec2022c, 0x111302, 0x30430fff, 0x24020001, 0x10620011, 0x28620002, 
 0x50400005, 0x24020002, 0x10600007, 0x0, 0x10000017, 0x0, 
 0x1062000f, 0x0, 0x10000013, 0x0, 0x8f460248, 0x24040001, 
-0xc004680, 0x24050004, 0x10000007, 0x0, 0x8f460248, 0x24040001, 
-0xc004680, 0x24050004, 0x10000010, 0x0, 0x8f46024c, 0x24040001, 
-0xc004680, 0x24050001, 0x1000000a, 0x0, 0x3c040001, 0x24842830, 
-0x3c050003, 0x34a50005, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, 
+0xc0046cc, 0x24050004, 0x10000007, 0x0, 0x8f460248, 0x24040001, 
+0xc0046cc, 0x24050004, 0x10000010, 0x0, 0x8f46024c, 0x24040001, 
+0xc0046cc, 0x24050001, 0x1000000a, 0x0, 0x3c040001, 0x24842960, 
+0x3c050003, 0x34a50005, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 
 0xafa00014, 0x8ec20228, 0x24420001, 0xaec20228, 0x1000013f, 0x8ec20228, 
 0xc002221, 0x0, 0x1000013b, 0x0, 0x24020001, 0xa2c20528, 
 0x24110014, 0x8ee404a0, 0x8ee504a4, 0xafb10010, 0xafa00014, 0x8ec20010, 
@@ -3639,8 +3661,8 @@
 0x0, 0x1000012a, 0x0, 0x3c020900, 0xaec00054, 0xaec00058, 
 0xaec0005c, 0xaec00060, 0xaec002c0, 0xa2c00065, 0xafa20020, 0x8ec3002c, 
 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 
-0x9821, 0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x248427dc, 
-0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 
+0x9821, 0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x2484290c, 
+0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 
 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006b, 0x8ec202a0, 
 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 
 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 
@@ -3649,7 +3671,7 @@
 0x1021, 0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 
 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 
 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 
-0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x248427e8, 
+0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x24842918, 
 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x1000002e, 
 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 
 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 
@@ -3657,33 +3679,33 @@
 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 0xafa20014, 0xafa30018, 
 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe4, 0x0, 
 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 0x0, 0x32a200ff, 
-0x1440000f, 0x0, 0x3c040001, 0x248427f4, 0xafa00010, 0xafa00014, 
-0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 0x0, 
+0x1440000f, 0x0, 0x3c040001, 0x24842924, 0xafa00010, 0xafa00014, 
+0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 
 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20218, 0x24420001, 
 0xaec20218, 0x8ec20218, 0x8ec2025c, 0x24420001, 0xaec2025c, 0x10000096, 
 0x8ec2025c, 0x8f42025c, 0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 
-0x24060008, 0xc00297e, 0xaec20160, 0x8f820220, 0x30420008, 0x14400002, 
+0x24060008, 0xc0029a2, 0xaec20160, 0x8f820220, 0x30420008, 0x14400002, 
 0x24020001, 0x24020002, 0xaec20200, 0x8ec20214, 0x24420001, 0xaec20214, 
 0x10000083, 0x8ec20214, 0x3c0200ff, 0x96e30462, 0x3442ffff, 0x2222024, 
 0x3402fffb, 0x44102b, 0x38420001, 0x30630003, 0x2c630001, 0x621824, 
-0x10600003, 0x0, 0x10000075, 0xaec40050, 0x3c040001, 0x2484283c, 
-0x3c050003, 0x34a5f00f, 0x2203021, 0x3821, 0xafa00010, 0xc0028eb, 
+0x10600003, 0x0, 0x10000075, 0xaec40050, 0x3c040001, 0x2484296c, 
+0x3c050003, 0x34a5f00f, 0x2203021, 0x3821, 0xafa00010, 0xc00290f, 
 0xafa00014, 0x3c030700, 0x34631000, 0x111602, 0x431025, 0xafa20020, 
 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 
 0x24510001, 0x8821, 0x8f420228, 0x1622000f, 0x4021, 0x3c040001, 
-0x248427bc, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
-0xc0028eb, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 
+0x248428ec, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
+0xc00290f, 0x34a5f005, 0x8ec202a0, 0x24420001, 0xaec202a0, 0x10000046, 
 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 
 0xac4304c0, 0xac4404c4, 0x8ec3002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 
 0x24070008, 0x2402000d, 0xafa20010, 0xafb10014, 0x8ec20008, 0x318c0, 
 0x604821, 0xa92821, 0xa9182b, 0x882021, 0x832021, 0x630c0, 
 0xafa20018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x5440000c, 
-0xaed1002c, 0x3c040001, 0x248427c8, 0xafa00010, 0xafa00014, 0x8ec6002c, 
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f000, 0x1000001d, 0x0, 
+0xaed1002c, 0x3c040001, 0x248428f8, 0xafa00010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f000, 0x1000001d, 0x0, 
 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 0x8ec80008, 0x8f860120, 0x24020011, 
 0xafa20010, 0xafa30014, 0xafa80018, 0x8ec200a8, 0x24070008, 0x40f809, 
-0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x248427d0, 0xafa00010, 
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f001, 
+0x24c6001c, 0x1440000e, 0x0, 0x3c040001, 0x24842900, 0xafa00010, 
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f001, 
 0x8ec202a4, 0x24420001, 0xaec202a4, 0x8ec202a4, 0x8ec20244, 0x24420001, 
 0xaec20244, 0x8ec20244, 0x8ec20254, 0x24420001, 0xaec20254, 0x8ec20254, 
 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 
@@ -3697,16 +3719,16 @@
 0xaf820220, 0x8f820200, 0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004, 
 0xaf820200, 0x8ede02bc, 0x8ec702c0, 0xafa70014, 0x8ec702c4, 0xafa7001c, 
 0x8ec20238, 0x26c40128, 0x24420001, 0xaec20238, 0x8ed10238, 0x8ed3016c, 
-0x8ed50168, 0xc00296c, 0x24050400, 0xaede02bc, 0x8fa70014, 0xaec702c0, 
+0x8ed50168, 0xc002990, 0x24050400, 0xaede02bc, 0x8fa70014, 0xaec702c0, 
 0x8fa7001c, 0xaec702c4, 0xaed10238, 0xaed3016c, 0xaed50168, 0x8f42025c, 
 0x26c4018c, 0xaec20158, 0x8f420260, 0x27450200, 0x24060008, 0xaec20160, 
-0x24020006, 0xc00297e, 0xaec2015c, 0x3c023b9a, 0x3442ca00, 0xaec20164, 
+0x24020006, 0xc0029a2, 0xaec2015c, 0x3c023b9a, 0x3442ca00, 0xaec20164, 
 0x240203e8, 0x24040002, 0x24030001, 0xaec201fc, 0xaec401f8, 0xaec30204, 
 0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaec30200, 0x10000003, 
-0x3021, 0xaec40200, 0x3021, 0x3c030001, 0x661821, 0x90633200, 
+0x3021, 0xaec40200, 0x3021, 0x3c030001, 0x661821, 0x90633360, 
 0x2c61021, 0x24c60001, 0xa0430194, 0x2cc2000f, 0x1440fff8, 0x2c61821, 
 0x24c60001, 0x8f820040, 0x27440080, 0x24050080, 0x21702, 0x24420030, 
-0xa0620194, 0x2c61021, 0xc00296c, 0xa0400194, 0x8fa70024, 0x30e20004, 
+0xa0620194, 0x2c61021, 0xc002990, 0xa0400194, 0x8fa70024, 0x30e20004, 
 0x14400006, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 
 0xaf820220, 0x8fa7002c, 0x30e20004, 0x14400006, 0x0, 0x8f820200, 
 0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, 0x8fbf0040, 0x8fbe003c, 
@@ -3736,11 +3758,11 @@
 0x431026, 0x2c460001, 0xc01021, 0x14400005, 0x510c0, 0x2e21021, 
 0x944575c0, 0x14a0ffed, 0x510c0, 0xa03021, 0x10c00010, 0x610c0, 
 0x571821, 0x8c6375c0, 0x571021, 0xafa30010, 0x8c4275c4, 0x3c040001, 
-0x2484294c, 0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc0028eb, 
+0x24842a7c, 0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc00290f, 
 0x34a5f012, 0x10000051, 0x3c020800, 0x8ec50124, 0x10a00004, 0x510c0, 
 0x2e21021, 0x944275c0, 0xaec20124, 0xa03021, 0x14c0000f, 0x27440212, 
-0x810c0, 0x2e21021, 0xafa80010, 0x944271c0, 0x3c040001, 0x24842958, 
-0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc0028eb, 0x34a5f013, 
+0x810c0, 0x2e21021, 0xafa80010, 0x944271c0, 0x3c040001, 0x24842a88, 
+0xafa20014, 0x8f460210, 0x8f470214, 0x3c050003, 0xc00290f, 0x34a5f013, 
 0x1000003a, 0x3c020800, 0x628c0, 0x94830000, 0xb71021, 0x244275c2, 
 0xa4430000, 0x8c830002, 0x820c0, 0xac430002, 0x2e41021, 0x944371c0, 
 0x2e51021, 0xa44375c0, 0x2e41021, 0xa44671c0, 0x8ec20120, 0x24420001, 
@@ -3753,8 +3775,8 @@
 0x24020001, 0x821004, 0x621825, 0xaca30228, 0x3c020800, 0x34421000, 
 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 0x8ec2002c, 
 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 0x0, 
-0x3c040001, 0x24842928, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
-0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 
+0x3c040001, 0x24842a58, 0xafa00010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
+0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 0xaec202a0, 
 0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 0x8ce30000, 
 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247103e8, 
 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000d, 0x8ec8002c, 
@@ -3763,16 +3785,16 @@
 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 0x24c604c0, 
 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 0x2221023, 
 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 0xaed3002c, 
-0x3c040001, 0x24842934, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
+0x3c040001, 0x24842a64, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 
 0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001, 0x24420001, 
 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 0x8f820054, 
 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400015, 0xa821, 0x24130011, 
 0x8ec30008, 0x8ee40488, 0x8ee5048c, 0x8ec2002c, 0x8f860120, 0xafb30010, 
 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 
 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffee, 
-0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842940, 
+0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842a70, 
 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 
-0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 
+0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 
 0x8ec2021c, 0x24420001, 0xaec2021c, 0x8ec2021c, 0x8ec20258, 0x24420001, 
 0xaec20258, 0x8ec20258, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 
 0x8fb10028, 0x3e00008, 0x27bd0040, 0x27bdffb0, 0x27440212, 0x24050006, 
@@ -3783,8 +3805,8 @@
 0x94a20004, 0x95230004, 0x431026, 0x2c460001, 0xc01021, 0x14400006, 
 0x710c0, 0xe04021, 0x2e21021, 0x944775c0, 0x14e0ffec, 0x710c0, 
 0xe02821, 0x14a0000f, 0xafa80028, 0x410c0, 0x2e21021, 0xafa40010, 
-0x944271c0, 0x3c040001, 0x24842964, 0xafa20014, 0x8f460210, 0x8f470214, 
-0x3c050003, 0xc0028eb, 0x34a5f01c, 0x10000062, 0x3c020800, 0x11000007, 
+0x944271c0, 0x3c040001, 0x24842a94, 0xafa20014, 0x8f460210, 0x8f470214, 
+0x3c050003, 0xc00290f, 0x34a5f01c, 0x10000062, 0x3c020800, 0x11000007, 
 0x510c0, 0x2e21021, 0x944375c0, 0x810c0, 0x2e21021, 0x10000006, 
 0xa44375c0, 0x2e21021, 0x944375c0, 0x410c0, 0x2e21021, 0xa44371c0, 
 0x8ec30124, 0x510c0, 0x2e21021, 0x26e871c0, 0xa44375c0, 0x8ec20120, 
@@ -3803,8 +3825,8 @@
 0x8c420228, 0x831804, 0x31827, 0x431024, 0xaca20228, 0x3c020800, 
 0x34422000, 0xafa20020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 
 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 
-0x0, 0x3c040001, 0x24842928, 0xafa00010, 0xafa00014, 0x8ec6002c, 
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 0x8ec202a0, 0x24420001, 
+0x0, 0x3c040001, 0x24842a58, 0xafa00010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 
 0xaec202a0, 0x1000006b, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 
 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 
 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000d, 
@@ -3813,7 +3835,7 @@
 0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 
 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 
 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 
-0xaed3002c, 0x3c040001, 0x24842934, 0xafa00010, 0xafa00014, 0x8f860120, 
+0xaed3002c, 0x3c040001, 0x24842a64, 0xafa00010, 0xafa00014, 0x8f860120, 
 0x8f870124, 0x3c050009, 0x1000002e, 0x34a5f010, 0x8ec2026c, 0x24150001, 
 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001d, 0x32a200ff, 0x8f830054, 
 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400015, 0xa821, 
@@ -3821,12 +3843,12 @@
 0xafb30010, 0xafa20014, 0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 
 0x24c6001c, 0x1440ffe4, 0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 
 0x1440ffee, 0x0, 0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 
-0x24842940, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 
-0x34a5f011, 0xc0028eb, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 
+0x24842a70, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 
+0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 
 0x8ec202d0, 0x8ec20220, 0x24420001, 0xaec20220, 0x8ec20220, 0x8ec20258, 
 0x24420001, 0xaec20258, 0x8ec20258, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 
 0x8fb3003c, 0x8fb10038, 0x3e00008, 0x27bd0050, 0x0, 0x0, 
-0x27bdffe8, 0x27644000, 0xafbf0010, 0xc00296c, 0x24051000, 0x24020020, 
+0x27bdffe8, 0x27644000, 0xafbf0010, 0xc002990, 0x24051000, 0x24020020, 
 0xaf82011c, 0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, 
 0xaf800118, 0xaf800120, 0xaf800124, 0xaf800128, 0xaf800130, 0xaf800134, 
 0xaf800138, 0xaec000dc, 0xaec000e0, 0xaec000e4, 0xaec000e8, 0x3c020001, 
@@ -3835,173 +3857,179 @@
 0x3c026000, 0x1062000b, 0x0, 0x10000010, 0x0, 0x8f420218, 
 0x30420040, 0x14400009, 0x0, 0x8f820050, 0x3c030010, 0x10000003, 
 0x431024, 0x8f420218, 0x30420040, 0x10400004, 0x0, 0x8f82011c, 
-0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8faa0010, 
-0x8f83012c, 0x8fab0014, 0x1060000c, 0x8fac0018, 0x8ec20534, 0x8f890128, 
-0x24680020, 0x51020005, 0x27624800, 0x11280005, 0x24620020, 0x10000009, 
-0x0, 0x15220007, 0x24620020, 0x8ec30298, 0x1021, 0x24630001, 
-0xaec30298, 0x1000006b, 0x8ec30298, 0xac640000, 0xac650004, 0xac660008, 
-0xa467000e, 0xac6a0018, 0xac6b001c, 0xac6c0010, 0x2543ffee, 0x2c630002, 
-0xaf820120, 0x39420011, 0x2c420001, 0x621825, 0x10600025, 0x0, 
-0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x8c830000, 0x24020012, 
-0x1462000f, 0x0, 0x8ec300e4, 0x8ec200e8, 0x1062000b, 0x24030040, 
-0x8c820004, 0x24420001, 0xac820004, 0x8ec200e8, 0x8ec500e4, 0x24420001, 
-0x1043002b, 0x0, 0x10000023, 0x0, 0x8ec200e4, 0x24030040, 
-0x24420001, 0x50430003, 0x1021, 0x8ec200e4, 0x24420001, 0xaec200e4, 
-0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x10000034, 0x24020012, 
-0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x8c830000, 0x24020007, 
-0x1462001f, 0x0, 0x8ec300e4, 0x8ec200e8, 0x1062001b, 0x24030040, 
-0x8c820004, 0x24420001, 0xac820004, 0x8ec200e8, 0x8ec500e4, 0x24420001, 
-0x10430007, 0x0, 0x8ec200e8, 0x24420001, 0x10a20005, 0x0, 
-0x10000007, 0x0, 0x14a00005, 0x0, 0x8f820128, 0x24420020, 
-0xaf820128, 0x8f820128, 0x8c820004, 0x2c420011, 0x50400013, 0xac800000, 
-0x10000012, 0x24020001, 0x8ec200e4, 0x24030040, 0x24420001, 0x50430003, 
-0x1021, 0x8ec200e4, 0x24420001, 0xaec200e4, 0x8ec200e4, 0x210c0, 
-0x24426fc0, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 
-0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x8faa0010, 
-0x8fab0014, 0x8f880120, 0x8ec20534, 0x8fac0018, 0x25030020, 0x14620002, 
-0x604821, 0x27694800, 0x8f820128, 0x1122000c, 0x25030016, 0xad040000, 
-0xad050004, 0xad060008, 0xa507000e, 0xad0a0018, 0xad0b001c, 0xad030014, 
-0xad0c0010, 0xaf890120, 0x10000006, 0x24020001, 0x8ec30298, 0x1021, 
-0x24630001, 0xaec30298, 0x8ec30298, 0x3e00008, 0x0, 0x3e00008, 
-0x0, 0x8faa0010, 0x8f83010c, 0x8fab0014, 0x1060000c, 0x8fac0018, 
-0x8f890108, 0x24680020, 0x27624800, 0x51020005, 0x27624000, 0x11280005, 
-0x24620020, 0x10000009, 0x0, 0x15220007, 0x24620020, 0x8ec3029c, 
-0x1021, 0x24630001, 0xaec3029c, 0x10000052, 0x8ec3029c, 0xac640000, 
-0xac650004, 0xac660008, 0xa467000e, 0xac6a0018, 0xac6b001c, 0xac6c0010, 
-0xaf820100, 0x2542fffb, 0x2c420002, 0x10400037, 0x24030040, 0x8ec200dc, 
-0x210c0, 0x24426dc0, 0x2e22021, 0x8c830000, 0x24020005, 0x1462001f, 
-0x0, 0x8ec300dc, 0x8ec200e0, 0x1062001b, 0x24030040, 0x8c820004, 
-0x24420001, 0xac820004, 0x8ec200e0, 0x8ec500dc, 0x24420001, 0x10430007, 
-0x0, 0x8ec200e0, 0x24420001, 0x10a20005, 0x0, 0x10000007, 
-0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 0xaf820108, 
-0x8f820108, 0x8c820004, 0x2c420011, 0x50400021, 0xac800000, 0x10000020, 
-0x24020001, 0x8ec200dc, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
-0x8ec200dc, 0x24420001, 0xaec200dc, 0x8ec200dc, 0x210c0, 0x24426dc0, 
-0x2e22021, 0x24020005, 0xac820000, 0x1000000e, 0x24020001, 0x8ec200dc, 
-0x24420001, 0x50430003, 0x1021, 0x8ec200dc, 0x24420001, 0xaec200dc, 
-0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x24020001, 0xac8a0000, 
-0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, 
-0x8f880100, 0x8fa30010, 0x8faa0014, 0x8fab0018, 0x27624800, 0x25090020, 
-0x122102b, 0x50400001, 0x27694000, 0x8f820108, 0x1122000d, 0x0, 
-0xad030018, 0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, 
-0xad0a001c, 0xad030014, 0xad0b0010, 0xaf890100, 0x10000006, 0x24020001, 
+0x34420004, 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x8fa90010, 
+0x8f83012c, 0x8faa0014, 0x8fab0018, 0x1060000a, 0x24680020, 0x8ec20534, 
+0x51020001, 0x27684800, 0x8f820128, 0x11020004, 0x0, 0x8f820124, 
+0x15020007, 0x39220011, 0x8ec30298, 0x1021, 0x24630001, 0xaec30298, 
+0x10000069, 0x8ec30298, 0xac640000, 0xac650004, 0xac660008, 0xa467000e, 
+0xac690018, 0xac6a001c, 0xac6b0010, 0x2523ffee, 0x2c630002, 0x2c420001, 
+0x621825, 0x10600025, 0xaf880120, 0x8ec200e4, 0x210c0, 0x24426fc0, 
+0x2e22021, 0x8c830000, 0x24020012, 0x1462000f, 0x0, 0x8ec300e4, 
+0x8ec200e8, 0x1062000b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
+0x8ec200e8, 0x8ec500e4, 0x24420001, 0x1043002b, 0x0, 0x10000023, 
+0x0, 0x8ec200e4, 0x24030040, 0x24420001, 0x50430003, 0x1021, 
+0x8ec200e4, 0x24420001, 0xaec200e4, 0x8ec200e4, 0x210c0, 0x24426fc0, 
+0x2e22021, 0x10000034, 0x24020012, 0x8ec200e4, 0x210c0, 0x24426fc0, 
+0x2e22021, 0x8c830000, 0x24020007, 0x1462001f, 0x0, 0x8ec300e4, 
+0x8ec200e8, 0x1062001b, 0x24030040, 0x8c820004, 0x24420001, 0xac820004, 
+0x8ec200e8, 0x8ec500e4, 0x24420001, 0x10430007, 0x0, 0x8ec200e8, 
+0x24420001, 0x10a20005, 0x0, 0x10000007, 0x0, 0x14a00005, 
+0x0, 0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x8c820004, 
+0x2c420011, 0x50400013, 0xac800000, 0x10000012, 0x24020001, 0x8ec200e4, 
+0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ec200e4, 0x24420001, 
+0xaec200e4, 0x8ec200e4, 0x210c0, 0x24426fc0, 0x2e22021, 0x24020007, 
+0xac820000, 0x24020001, 0xac820004, 0x24020001, 0x3e00008, 0x0, 
+0x3e00008, 0x0, 0x8faa0010, 0x8fab0014, 0x8f880120, 0x8ec20534, 
+0x8fac0018, 0x25030020, 0x14620002, 0x604821, 0x27694800, 0x8f820128, 
+0x1122000c, 0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, 
+0xad0a0018, 0xad0b001c, 0xad030014, 0xad0c0010, 0xaf890120, 0x10000006, 
+0x24020001, 0x8ec30298, 0x1021, 0x24630001, 0xaec30298, 0x8ec30298, 
+0x3e00008, 0x0, 0x3e00008, 0x0, 0x8fa90010, 0x8f83010c, 
+0x8faa0014, 0x8fab0018, 0x1060000a, 0x24680020, 0x27624800, 0x51020001, 
+0x27684000, 0x8f820108, 0x11020004, 0x0, 0x8f820104, 0x15020007, 
+0x2522fffb, 0x8ec3029c, 0x1021, 0x24630001, 0xaec3029c, 0x10000051, 
+0x8ec3029c, 0x2c420002, 0xac640000, 0xac650004, 0xac660008, 0xa467000e, 
+0xac690018, 0xac6a001c, 0xac6b0010, 0xaf880100, 0x10400037, 0x24030040, 
+0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x8c830000, 0x24020005, 
+0x1462001f, 0x0, 0x8ec300dc, 0x8ec200e0, 0x1062001b, 0x24030040, 
+0x8c820004, 0x24420001, 0xac820004, 0x8ec200e0, 0x8ec500dc, 0x24420001, 
+0x10430007, 0x0, 0x8ec200e0, 0x24420001, 0x10a20005, 0x0, 
+0x10000007, 0x0, 0x14a00005, 0x0, 0x8f820108, 0x24420020, 
+0xaf820108, 0x8f820108, 0x8c820004, 0x2c420011, 0x50400021, 0xac800000, 
+0x10000020, 0x24020001, 0x8ec200dc, 0x24030040, 0x24420001, 0x50430003, 
+0x1021, 0x8ec200dc, 0x24420001, 0xaec200dc, 0x8ec200dc, 0x210c0, 
+0x24426dc0, 0x2e22021, 0x24020005, 0xac820000, 0x1000000e, 0x24020001, 
+0x8ec200dc, 0x24420001, 0x50430003, 0x1021, 0x8ec200dc, 0x24420001, 
+0xaec200dc, 0x8ec200dc, 0x210c0, 0x24426dc0, 0x2e22021, 0x24020001, 
+0xac890000, 0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, 
+0x0, 0x8fab0010, 0x8f880100, 0x8faa0014, 0x8fac0018, 0x27624800, 
+0x25030020, 0x14620002, 0x604821, 0x27694000, 0x8f820108, 0x1122000c, 
+0x25030016, 0xad040000, 0xad050004, 0xad060008, 0xa507000e, 0xad0b0018, 
+0xad0a001c, 0xad030014, 0xad0c0010, 0xaf890100, 0x10000006, 0x24020001, 
 0x8ec3029c, 0x1021, 0x24630001, 0xaec3029c, 0x8ec3029c, 0x3e00008, 
 0x0, 0x3e00008, 0x0, 0x27bdffe0, 0xafbf0018, 0x8f820104, 
-0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, 0x8f87011c, 
-0x3c040001, 0x24842a2c, 0xc0028eb, 0x34a5f000, 0x8f420218, 0x30420100, 
+0xafa20010, 0x8f820100, 0x3c040001, 0x24842b5c, 0xafa20014, 0x8f8600b0, 
+0x8f87011c, 0x3c050002, 0xc00290f, 0x34a5f000, 0x8f420218, 0x30420100, 
 0x10400017, 0x0, 0x8f8200b0, 0x3c030200, 0x431024, 0x10400012, 
 0x0, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 
 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f82011c, 0x2403fffd, 0x431024, 
-0xaf82011c, 0x8ec20294, 0x24420001, 0xaec20294, 0x10000004, 0x8ec20294, 
-0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, 0x3e00008, 0x27bd0020, 
-0x27bdffe0, 0xafbf0018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, 
-0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001, 0x24842a38, 0xc0028eb, 
-0x34a5f000, 0x8f420218, 0x30420100, 0x10400017, 0x0, 0x8f8200a0, 
-0x3c030200, 0x431024, 0x10400012, 0x0, 0x8f82011c, 0x34420002, 
-0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0xaf830124, 
-0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ec20290, 0x24420001, 
-0xaec20290, 0x10000004, 0x8ec20290, 0x8f8200a0, 0x34420001, 0xaf8200a0, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x6021, 0x5021, 0x3021, 
-0x2821, 0x6821, 0x4821, 0x7821, 0x7021, 0x8f880124, 
-0x8f870104, 0x1580002e, 0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, 
-0x10460029, 0x0, 0x3c040001, 0x8c843390, 0x8cc20000, 0x8cc30004, 
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 
-0x10400017, 0x0, 0x3c040001, 0x8c843390, 0x8d020000, 0x8d030004, 
-0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021, 
-0x1540002f, 0x31620100, 0x11200014, 0x31628000, 0x8f820100, 0x1045002a, 
-0x31620100, 0x3c040001, 0x8c84338c, 0x8ca20000, 0x8ca30004, 0xac820000, 
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 
-0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 
-0x31620100, 0x3c040001, 0x8c84338c, 0x8ce20000, 0x8ce30004, 0xac820000, 
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 
-0x24e50020, 0xac820010, 0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, 
-0x276247e0, 0x43102b, 0x54400001, 0x27634000, 0x602821, 0x31620100, 
-0x5440001d, 0x31621000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, 
-0x11800011, 0x31621000, 0x3c040001, 0x8c843390, 0x8c820000, 0x8c830004, 
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, 
-0x1440ff82, 0x0, 0x1120000f, 0x31220800, 0x10400004, 0x3c020002, 
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x4821, 
-0x1140ff70, 0x0, 0x3c040001, 0x8c84338c, 0x8c820000, 0x8c830004, 
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 
-0x8c820010, 0x5021, 0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, 
-0x3e00008, 0x0, 0x6021, 0x5821, 0x3021, 0x2821, 
-0x6821, 0x5021, 0x7821, 0x7021, 0x8f880124, 0x8f870104, 
-0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, 
-0x10460029, 0x0, 0x3c040001, 0x8c843390, 0x8cc20000, 0x8cc30004, 
-0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 
-0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 
-0x10400017, 0x0, 0x3c040001, 0x8c843390, 0x8d020000, 0x8d030004, 
-0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 
-0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 
-0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021, 
-0x1560002f, 0x31220100, 0x11400014, 0x31228000, 0x8f820100, 0x1045002a, 
-0x31220100, 0x3c040001, 0x8c84338c, 0x8ca20000, 0x8ca30004, 0xac820000, 
-0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 
-0x240b0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 
-0x31220100, 0x3c040001, 0x8c84338c, 0x8ce20000, 0x8ce30004, 0xac820000, 
-0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 
-0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, 0xa01821, 0xac820014, 
-0x276247e0, 0x43102b, 0x54400001, 0x27634000, 0x602821, 0x31220100, 
-0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 
-0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, 
-0x11800011, 0x31221000, 0x3c040001, 0x8c843390, 0x8c820000, 0x8c830004, 
-0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 
-0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31221000, 
-0x14400022, 0x0, 0x1140000f, 0x31420800, 0x10400004, 0x3c020002, 
-0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 0x10400004, 0x24e20020, 
-0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x5021, 
-0x11600010, 0x0, 0x3c040001, 0x8c84338c, 0x8c820000, 0x8c830004, 
-0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 
-0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, 0x8c8e0014, 0x8f820070, 
-0x3c031000, 0x431024, 0x1040ff5c, 0x0, 0x8f820054, 0x24420005, 
-0xaf820078, 0x8f420234, 0x10400017, 0x2021, 0x3c020001, 0x571021, 
-0x8c4281dc, 0x24420005, 0x3c010001, 0x370821, 0xac2281dc, 0x3c020001, 
-0x571021, 0x8c4281dc, 0x8f430234, 0x43102b, 0x14400009, 0x24020001, 
-0x3c040080, 0x3c010001, 0x370821, 0xac2281d4, 0x3c010001, 0x370821, 
-0x1000000c, 0xac2081dc, 0x3c020001, 0x571021, 0x8c4281d4, 0x14400006, 
-0x3c020080, 0x3c020001, 0x571021, 0x8c4281d8, 0x10400002, 0x3c020080, 
-0x822025, 0x8f420230, 0x10400014, 0x0, 0x3c020001, 0x571021, 
-0x8c4281e4, 0x24420005, 0x3c010001, 0x370821, 0xac2281e4, 0x3c020001, 
-0x571021, 0x8c4281e4, 0x8f430230, 0x43102b, 0x14400006, 0x0, 
-0x3c010001, 0x370821, 0xac2081e4, 0x10000006, 0x982025, 0x3c020001, 
-0x571021, 0x8c4281e0, 0x54400001, 0x982025, 0x3c020001, 0x571021, 
-0x8c4281e8, 0x10400005, 0x3c022000, 0x822025, 0x3c010001, 0x370821, 
-0xac2081e8, 0x1080ff0f, 0x0, 0x8ec20000, 0x10400007, 0x0, 
-0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 
-0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x441025, 
-0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x1000fefa, 0xaf80004c, 
-0x1000fef8, 0xaf800048, 0x3e00008, 0x0, 0x3c020001, 0x8c423228, 
-0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb10010, 0x3c110001, 0x26313430, 
-0x2202021, 0xc00296c, 0x24052000, 0x26221fe0, 0x3c010001, 0xac223398, 
-0x3c010001, 0xac223394, 0xaf420250, 0x24022000, 0xaf510254, 0xaf420258, 
-0x24020001, 0x3c010001, 0xac223228, 0x8fbf0014, 0x8fb10010, 0x3e00008, 
-0x27bd0018, 0x3c030001, 0x8c633398, 0x8c820000, 0x8fa80010, 0x8fa90014, 
-0xac620000, 0x3c020001, 0x8c423398, 0x8c830004, 0xac430004, 0xac450008, 
+0xaf82011c, 0x8ec20294, 0x24420001, 0xaec20294, 0x10000018, 0x8ec20294, 
+0x3c040001, 0x24842b68, 0x3405dead, 0x3021, 0x3c070001, 0x24e72b70, 
+0x24020287, 0xafa20010, 0xc00290f, 0xafa00014, 0x8f82011c, 0x34420002, 
+0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 
+0x431025, 0xaf820140, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x8fbf0018, 
+0x3e00008, 0x27bd0020, 0x27bdffe0, 0xafbf0018, 0x8f820120, 0xafa20010, 
+0x8f820124, 0x3c040001, 0x24842b98, 0xafa20014, 0x8f8600a0, 0x8f87011c, 
+0x3c050001, 0xc00290f, 0x34a5f000, 0x8f420218, 0x30420100, 0x10400017, 
+0x0, 0x8f8200a0, 0x3c030200, 0x431024, 0x10400012, 0x0, 
+0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 
+0xaf8200a0, 0xaf830124, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 
+0x8ec20290, 0x24420001, 0xaec20290, 0x10000018, 0x8ec20290, 0x3c040001, 
+0x24842b68, 0x3405dead, 0x3021, 0x3c070001, 0x24e72b70, 0x240202a3, 
+0xafa20010, 0xc00290f, 0xafa00014, 0x8f82011c, 0x34420002, 0xaf82011c, 
+0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025, 
+0xaf820140, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x6021, 0x5021, 0x3021, 0x2821, 0x6821, 
+0x4821, 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x1580002e, 
+0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, 0x10460029, 0x0, 
+0x3c040001, 0x8c8434f0, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0, 
+0x3c040001, 0x8c8434f0, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, 
+0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1540002f, 0x31620100, 
+0x11200014, 0x31628000, 0x8f820100, 0x1045002a, 0x31620100, 0x3c040001, 
+0x8c8434ec, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240a0001, 0xac820010, 
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31620100, 0x3c040001, 
+0x8c8434ec, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 
+0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, 0x276247e0, 0x43102b, 
+0x54400001, 0x27634000, 0x602821, 0x31620100, 0x5440001d, 0x31621000, 
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 
+0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31621000, 
+0x3c040001, 0x8c8434f0, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, 0x1440ff82, 0x0, 
+0x1120000f, 0x31220800, 0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000, 
+0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 
+0x24e20020, 0xaf820104, 0x8f870104, 0x4821, 0x1140ff70, 0x0, 
+0x3c040001, 0x8c8434ec, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5021, 
+0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, 0x3e00008, 0x0, 
+0x6021, 0x5821, 0x3021, 0x2821, 0x6821, 0x5021, 
+0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x3c180100, 0x1580002e, 
+0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, 0x10460029, 0x0, 
+0x3c040001, 0x8c8434f0, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 
+0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 
+0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0, 
+0x3c040001, 0x8c8434f0, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 
+0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 
+0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, 
+0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1560002f, 0x31220100, 
+0x11400014, 0x31228000, 0x8f820100, 0x1045002a, 0x31220100, 0x3c040001, 
+0x8c8434ec, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 
+0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010, 
+0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31220100, 0x3c040001, 
+0x8c8434ec, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 
+0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 
+0x8ce20014, 0x240b0001, 0xa01821, 0xac820014, 0x276247e0, 0x43102b, 
+0x54400001, 0x27634000, 0x602821, 0x31220100, 0x5440001d, 0x31221000, 
+0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 
+0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31221000, 
+0x3c040001, 0x8c8434f0, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 
+0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 
+0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31221000, 0x14400022, 0x0, 
+0x1140000f, 0x31420800, 0x10400004, 0x3c020002, 0x8f8200b8, 0xa5c20000, 
+0x3c020002, 0x1421024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 
+0x24e20020, 0xaf820104, 0x8f870104, 0x5021, 0x11600010, 0x0, 
+0x3c040001, 0x8c8434ec, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 
+0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5821, 
+0xaf8200b0, 0x8c8a0010, 0x8c8e0014, 0x8f820070, 0x3c031000, 0x431024, 
+0x1040ff5c, 0x0, 0x8f820054, 0x24420005, 0xaf820078, 0x8f420234, 
+0x10400017, 0x2021, 0x3c020001, 0x571021, 0x8c4281dc, 0x24420005, 
+0x3c010001, 0x370821, 0xac2281dc, 0x3c020001, 0x571021, 0x8c4281dc, 
+0x8f430234, 0x43102b, 0x14400009, 0x24020001, 0x3c040080, 0x3c010001, 
+0x370821, 0xac2281d4, 0x3c010001, 0x370821, 0x1000000c, 0xac2081dc, 
+0x3c020001, 0x571021, 0x8c4281d4, 0x14400006, 0x3c020080, 0x3c020001, 
+0x571021, 0x8c4281d8, 0x10400002, 0x3c020080, 0x822025, 0x8f420230, 
+0x10400014, 0x0, 0x3c020001, 0x571021, 0x8c4281e4, 0x24420005, 
+0x3c010001, 0x370821, 0xac2281e4, 0x3c020001, 0x571021, 0x8c4281e4, 
+0x8f430230, 0x43102b, 0x14400006, 0x0, 0x3c010001, 0x370821, 
+0xac2081e4, 0x10000006, 0x982025, 0x3c020001, 0x571021, 0x8c4281e0, 
+0x54400001, 0x982025, 0x3c020001, 0x571021, 0x8c4281e8, 0x10400005, 
+0x3c022000, 0x822025, 0x3c010001, 0x370821, 0xac2081e8, 0x1080ff0f, 
+0x0, 0x8ec20000, 0x10400007, 0x0, 0xaf80004c, 0x8f82004c, 
+0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, 
+0x1040fffd, 0x0, 0x8f820060, 0x441025, 0xaf820060, 0x8ec20000, 
+0x10400003, 0x0, 0x1000fefa, 0xaf80004c, 0x1000fef8, 0xaf800048, 
+0x3e00008, 0x0, 0x0, 0x0, 0x3c020001, 0x8c423388, 
+0x27bdffe8, 0xafbf0014, 0x14400012, 0xafb10010, 0x3c110001, 0x26313590, 
+0x2202021, 0xc002990, 0x24052000, 0x26221fe0, 0x3c010001, 0xac2234f8, 
+0x3c010001, 0xac2234f4, 0xaf420250, 0x24022000, 0xaf510254, 0xaf420258, 
+0x24020001, 0x3c010001, 0xac223388, 0x8fbf0014, 0x8fb10010, 0x3e00008, 
+0x27bd0018, 0x3c030001, 0x8c6334f8, 0x8c820000, 0x8fa80010, 0x8fa90014, 
+0xac620000, 0x3c020001, 0x8c4234f8, 0x8c830004, 0xac430004, 0xac450008, 
 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, 0xac480018, 0xac49001c, 
-0x3c010001, 0xac233398, 0xac44000c, 0x3c020001, 0x24423430, 0x62182b, 
-0x10600005, 0x0, 0x3c020001, 0x8c423394, 0x3c010001, 0xac223398, 
-0x3c030001, 0x8c633398, 0x3c020001, 0x8c423210, 0xac620000, 0x3c030001, 
-0x8c633398, 0x3c020001, 0x8c423210, 0xac620004, 0x3e00008, 0xaf430250, 
-0x27bdffd8, 0xafb10010, 0x808821, 0x3c030001, 0x8c633398, 0x3c020001, 
-0x8c423210, 0x8fa40040, 0xafb30014, 0xa09821, 0xafbf0020, 0xafbe001c, 
-0xafb50018, 0xac620000, 0x3c050001, 0x8ca53398, 0x3c020001, 0x8c423210, 
-0xc0a821, 0xe0f021, 0x10800006, 0xaca20004, 0x24a50008, 0xc002974, 
-0x24060018, 0x10000004, 0x0, 0x24a40008, 0xc00296c, 0x24050018, 
-0x3c020001, 0x8c423398, 0x3c050001, 0x24a53430, 0x2442ffe0, 0x3c010001, 
-0xac223398, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c423394, 
-0x3c010001, 0xac223398, 0x3c030001, 0x8c633398, 0x8e220000, 0xac620000, 
-0x3c030001, 0x8c633398, 0x8e220004, 0xac620004, 0xac730008, 0x8f840054, 
+0x3c010001, 0xac2334f8, 0xac44000c, 0x3c020001, 0x24423590, 0x62182b, 
+0x10600005, 0x0, 0x3c020001, 0x8c4234f4, 0x3c010001, 0xac2234f8, 
+0x3c030001, 0x8c6334f8, 0x3c020001, 0x8c423370, 0xac620000, 0x3c030001, 
+0x8c6334f8, 0x3c020001, 0x8c423370, 0xac620004, 0x3e00008, 0xaf430250, 
+0x27bdffd8, 0xafb10010, 0x808821, 0x3c030001, 0x8c6334f8, 0x3c020001, 
+0x8c423370, 0x8fa40040, 0xafb30014, 0xa09821, 0xafbf0020, 0xafbe001c, 
+0xafb50018, 0xac620000, 0x3c050001, 0x8ca534f8, 0x3c020001, 0x8c423370, 
+0xc0a821, 0xe0f021, 0x10800006, 0xaca20004, 0x24a50008, 0xc002998, 
+0x24060018, 0x10000004, 0x0, 0x24a40008, 0xc002990, 0x24050018, 
+0x3c020001, 0x8c4234f8, 0x3c050001, 0x24a53590, 0x2442ffe0, 0x3c010001, 
+0xac2234f8, 0x45102b, 0x10400005, 0x0, 0x3c020001, 0x8c4234f4, 
+0x3c010001, 0xac2234f8, 0x3c030001, 0x8c6334f8, 0x8e220000, 0xac620000, 
+0x3c030001, 0x8c6334f8, 0x8e220004, 0xac620004, 0xac730008, 0x8f840054, 
 0xac750010, 0xac7e0014, 0x8fa80038, 0xac680018, 0x8fa8003c, 0x2462ffe0, 
-0x3c010001, 0xac223398, 0x45102b, 0xac68001c, 0x10400005, 0xac64000c, 
-0x3c020001, 0x8c423394, 0x3c010001, 0xac223398, 0x3c030001, 0x8c633398, 
-0x3c020001, 0x8c423210, 0xac620000, 0x3c030001, 0x8c633398, 0x3c020001, 
-0x8c423210, 0xac620004, 0xaf430250, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 
+0x3c010001, 0xac2234f8, 0x45102b, 0xac68001c, 0x10400005, 0xac64000c, 
+0x3c020001, 0x8c4234f4, 0x3c010001, 0xac2234f8, 0x3c030001, 0x8c6334f8, 
+0x3c020001, 0x8c423370, 0xac620000, 0x3c030001, 0x8c6334f8, 0x3c020001, 
+0x8c423370, 0xac620004, 0xaf430250, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 
 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x10a00005, 0x0, 
 0xac800000, 0x24a5fffc, 0x14a0fffd, 0x24840004, 0x3e00008, 0x0, 
 0x10c00007, 0x0, 0x8c820000, 0x24840004, 0x24c6fffc, 0xaca20000, 
@@ -4025,7 +4053,7 @@
 0x24020017, 0x24020006, 0xafa20010, 0x8ec2001c, 0xafa20014, 0x8ec2000c, 
 0x8fa40028, 0x8fa5002c, 0x3c030002, 0x431025, 0xafa20018, 0x8ec60080, 
 0x8ec200a4, 0x40f809, 0x0, 0x5440000b, 0x3225ffff, 0x8fa9002c, 
-0xafa90010, 0x8ec20080, 0x3c040001, 0x24842cfc, 0x3c050004, 0xafa20014, 
+0xafa90010, 0x8ec20080, 0x3c040001, 0x24842e5c, 0x3c050004, 0xafa20014, 
 0x8ec6001c, 0x100000a5, 0x34a5f004, 0x8ec20078, 0x451021, 0xaec20078, 
 0x8ec2001c, 0x8ee304bc, 0x8ec40074, 0x21100, 0x431021, 0xac44000c, 
 0x8ec30074, 0xafa30020, 0x8ec40078, 0xafa40024, 0x8ec2052c, 0x10400006, 
@@ -4037,8 +4065,8 @@
 0x0, 0x8ec202a8, 0x1821, 0x24420001, 0xaec202a8, 0x10000008, 
 0x8ec202a8, 0x8fa20020, 0x8fa30024, 0xacc20000, 0xacc30004, 0x24c20008, 
 0xaf8200f0, 0x24030001, 0x14600012, 0x131142, 0x8f8200f0, 0xafa20010, 
-0x8f8200f4, 0x3c040001, 0x24842d08, 0xafa20014, 0x8fa60020, 0x8fa70024, 
-0x3c050004, 0xc0028eb, 0x34a5f005, 0x8ec20180, 0x24420001, 0xaec20180, 
+0x8f8200f4, 0x3c040001, 0x24842e68, 0xafa20014, 0x8fa60020, 0x8fa70024, 
+0x3c050004, 0xc00290f, 0x34a5f005, 0x8ec20180, 0x24420001, 0xaec20180, 
 0x8ec20180, 0x10000039, 0x24020001, 0x30430003, 0x24020002, 0x10620016, 
 0x28620003, 0x10400005, 0x24020001, 0x10620008, 0x0, 0x10000023, 
 0x0, 0x24020003, 0x10620017, 0x0, 0x1000001e, 0x0, 
@@ -4052,8 +4080,8 @@
 0x1000002f, 0xa2c20529, 0x3227ffff, 0x10e0002c, 0x0, 0x14400002, 
 0x24020016, 0x24020005, 0xafa20010, 0x8ec2001c, 0x8fa40028, 0x8fa5002c, 
 0xafa20014, 0x8ec2000c, 0xafa20018, 0x8ec60080, 0x8ec200a4, 0x40f809, 
-0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842d14, 0x8fa8002c, 
-0x3c050004, 0xafa00014, 0xafa80010, 0x8ec6001c, 0x34a5f007, 0xc0028eb, 
+0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842e74, 0x8fa8002c, 
+0x3c050004, 0xafa00014, 0xafa80010, 0x8ec6001c, 0x34a5f007, 0xc00290f, 
 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, 0x451021, 
 0xaec20080, 0x8ec20078, 0x8ec30080, 0x451021, 0x64182b, 0x14600005, 
 0xaec20078, 0x8ec20080, 0x8ec3053c, 0x431023, 0xaec20080, 0xa2c00529, 
@@ -4086,7 +4114,7 @@
 0xafa20010, 0x8ec2001c, 0x8fa40020, 0x8fa50024, 0x3c030002, 0xc31825, 
 0xafa30018, 0xafa20014, 0x8ec60080, 0x8ec200a4, 0x40f809, 0x0, 
 0x1440000b, 0x24030001, 0x8fab0024, 0xafab0010, 0x8ec20080, 0x3c040001, 
-0x24842cfc, 0x3c050004, 0xafa20014, 0x8ec60018, 0x10000037, 0x34a5f004, 
+0x24842e5c, 0x3c050004, 0xafa20014, 0x8ec60018, 0x10000037, 0x34a5f004, 
 0x8ec40070, 0x8ec20080, 0x8ec50538, 0x2406fff8, 0xa2c30021, 0xaec0052c, 
 0xaec00530, 0x24840001, 0xaec40070, 0x3224ffff, 0x441021, 0x24420007, 
 0x461024, 0x24840007, 0xaec20074, 0x8ec20088, 0x8ec30074, 0x862024, 
@@ -4094,9 +4122,9 @@
 0x431023, 0xaec20074, 0x8ec20074, 0x1000002d, 0xaec20080, 0x10e0002b, 
 0x0, 0x15000002, 0x24020016, 0x24020005, 0xafa20010, 0x8ec2001c, 
 0x8fa40020, 0x8fa50024, 0xafa60018, 0xafa20014, 0x8ec60080, 0x8ec200a4, 
-0x40f809, 0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842d14, 
+0x40f809, 0x0, 0x1440000d, 0x3225ffff, 0x3c040001, 0x24842e74, 
 0x8faa0024, 0x3c050004, 0xafa00014, 0xafaa0010, 0x8ec60018, 0x34a5f007, 
-0xc0028eb, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, 
+0xc00290f, 0x2203821, 0x10000030, 0x0, 0x8ec20080, 0x8ec40538, 
 0x451021, 0xaec20080, 0x8ec20088, 0x8ec30080, 0xa2c00021, 0x451023, 
 0x64182b, 0x14600005, 0xaec20088, 0x8ec20080, 0x8ec3053c, 0x431023, 
 0xaec20080, 0x8ec3001c, 0x96e20450, 0x24630001, 0x2442ffff, 0x621824, 
@@ -4119,26 +4147,26 @@
 0x0, 0x96e20452, 0x8ed10018, 0x30420020, 0x1040001e, 0x24070008, 
 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 
 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 
-0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x1040004a, 
+0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040004a, 
 0x24020001, 0x3c010001, 0x370821, 0x1000006f, 0xac2281d0, 0x8ee40498, 
 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 
 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 
-0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
-0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x1040004f, 0x24020001, 
+0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
+0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x1040004f, 0x24020001, 
 0x10000051, 0x0, 0x2c420002, 0x10400062, 0x24a2fffe, 0x8cc2001c, 
 0x96e30450, 0x8ec40024, 0x24420001, 0x2463ffff, 0x431024, 0x872021, 
 0xaec20018, 0xaec40024, 0x96e20452, 0x8ed10018, 0x30420020, 0x10400023, 
 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 
 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 
-0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 
+0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 
 0x14400006, 0x24020001, 0x24020001, 0x3c010001, 0x370821, 0x10000031, 
 0xac2281d8, 0x3c010001, 0x370821, 0x10000021, 0xac2281d0, 0x8ee40498, 
 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 
 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 
-0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
-0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 
+0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 
+0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 
 0x3c010001, 0x370821, 0x10000010, 0xac2281d4, 0x3c010001, 0x370821, 
 0xac2081d0, 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 
 0xac2081d4, 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 
@@ -4150,12 +4178,12 @@
 0x8ec202c4, 0x641821, 0x306300ff, 0x10000009, 0xaec3005c, 0x8ec202bc, 
 0x8ec3003c, 0x441021, 0xaec202bc, 0x8ec202c4, 0x641821, 0x306301ff, 
 0xaec3003c, 0x441021, 0xaec202c4, 0x10000022, 0x36940040, 0x24020014, 
-0x14a20014, 0x24020010, 0x3c020001, 0x8c4231d4, 0x1040000a, 0x26e50028, 
+0x14a20014, 0x24020010, 0x3c020001, 0x8c423334, 0x1040000a, 0x26e50028, 
 0x26c40128, 0x240300ff, 0x2406ffff, 0x8ca20000, 0x24a50004, 0x2463ffff, 
 0xac820000, 0x1466fffb, 0x24840004, 0x8ec20240, 0xa2c00528, 0x24420001, 
 0xaec20240, 0x1000000c, 0x8ec20240, 0x10a2000a, 0x3c050008, 0x94c7000e, 
-0x8cc2001c, 0x3c040001, 0x24842d20, 0xafa60014, 0xafa20010, 0x8cc60018, 
-0xc0028eb, 0x34a50910, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 
+0x8cc2001c, 0x3c040001, 0x24842e80, 0xafa60014, 0xafa20010, 0x8cc60018, 
+0xc00290f, 0x34a50910, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 
 0x3e00008, 0x0, 0x27bdff80, 0xafbf0078, 0xafbe0074, 0xafb50070, 
 0xafb3006c, 0xafb10068, 0x8f820104, 0x8f950108, 0xafa00034, 0x12a2039b, 
 0xafa0003c, 0x8f820108, 0x24420020, 0xaf820108, 0x8ead0018, 0xafad0044, 
@@ -4185,8 +4213,8 @@
 0xaecd0094, 0x8ec3009c, 0x8ec20538, 0x24650017, 0xa2102b, 0x14400003, 
 0x0, 0x8ec2053c, 0xa22823, 0x90a50000, 0xa3a5005f, 0x93a6005f, 
 0x38c30006, 0x3182b, 0x38c20011, 0x2102b, 0x621824, 0x1060000c, 
-0x3c050008, 0x8fad0054, 0xafad0010, 0x8ec2009c, 0x3c040001, 0x24842d2c, 
-0xafa20014, 0x8ec70094, 0xc0028eb, 0x34a5f055, 0x100000d7, 0x0, 
+0x3c050008, 0x8fad0054, 0xafad0010, 0x8ec2009c, 0x3c040001, 0x24842e8c, 
+0xafa20014, 0x8ec70094, 0xc00290f, 0x34a5f055, 0x100000d7, 0x0, 
 0x96e20452, 0x30420008, 0x1040000c, 0x2625000e, 0x8ec20538, 0xa2102b, 
 0x14400003, 0xf021, 0x8ec2053c, 0xa22823, 0x90a20000, 0x3042000f, 
 0x21080, 0x10000068, 0xafa20028, 0x8ec20094, 0x8fad0054, 0x11a20013, 
@@ -4264,13 +4292,13 @@
 0x2c420002, 0x1040012f, 0x0, 0x96e20452, 0x8ed10018, 0x30420020, 
 0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 
 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 
-0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 
+0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 
+0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 
 0x1021, 0x1040008f, 0x24020001, 0x3c010001, 0x370821, 0x100000b4, 
 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020012, 
 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 
-0x1440000b, 0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 
-0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 
+0x1440000b, 0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 
+0x8ec6002c, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 
 0x10400094, 0x24020001, 0x10000096, 0x0, 0x15a20043, 0x24020016, 
 0x96a3000e, 0x8ec20078, 0x8ec40024, 0x431021, 0xaec20078, 0x8ea3001c, 
 0x96e20450, 0x24840001, 0xaec40024, 0x24630001, 0x2442ffff, 0x621824, 
@@ -4278,8 +4306,8 @@
 0x8ed10018, 0x30420020, 0x1040001e, 0x24070008, 0x8ee40498, 0x8ee5049c, 
 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 0xafb10014, 0xafa30018, 
 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 
-0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
-0xc0028eb, 0x34a5f006, 0x1021, 0x1040003f, 0x24020001, 0x3c010001, 
+0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
+0xc00290f, 0x34a5f006, 0x1021, 0x1040003f, 0x24020001, 0x3c010001, 
 0x370821, 0x10000064, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 0x8ec30008, 
 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 
 0x40f809, 0x24c6001c, 0x1040ffb1, 0x0, 0x1000ffb9, 0x24020001, 
@@ -4288,14 +4316,14 @@
 0xaec30018, 0x96e20452, 0x8ed10018, 0x30420020, 0x10400023, 0x24070008, 
 0x8ee40498, 0x8ee5049c, 0x8ec30008, 0x8f860120, 0x24020019, 0xafa20010, 
 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 
-0x24020001, 0x3c040001, 0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 
-0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f006, 0x1021, 0x14400006, 
+0x24020001, 0x3c040001, 0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f006, 0x1021, 0x14400006, 
 0x24020001, 0x24020001, 0x3c010001, 0x370821, 0x10000031, 0xac2281d8, 
 0x3c010001, 0x370821, 0x10000021, 0xac2281d0, 0x8ee40498, 0x8ee5049c, 
 0x8ec30008, 0x8f860120, 0x24020012, 0xafa20010, 0xafb10014, 0xafa30018, 
 0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 
-0x24842ca0, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
-0xc0028eb, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 
+0x24842e00, 0xafb10010, 0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 
+0xc00290f, 0x34a5f006, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 
 0x370821, 0x10000010, 0xac2281d4, 0x3c010001, 0x370821, 0xac2081d0, 
 0x3c010001, 0x370821, 0xac2081d8, 0x3c010001, 0x370821, 0xac2081d4, 
 0x8ec20264, 0xaec00024, 0xaed10028, 0x24420001, 0xaec20264, 0x8ec20264, 
@@ -4307,11 +4335,11 @@
 0x8ec202c4, 0x641821, 0x306300ff, 0x10000009, 0xaec3005c, 0x8ec202bc, 
 0x8ec3003c, 0x441021, 0xaec202bc, 0x8ec202c4, 0x641821, 0x306301ff, 
 0xaec3003c, 0x441021, 0xaec202c4, 0x1000001f, 0x36940040, 0x8fad0044, 
-0x24020014, 0x15a20010, 0x24020010, 0x3c020001, 0x8c4231d4, 0x10400017, 
+0x24020014, 0x15a20010, 0x24020010, 0x3c020001, 0x8c423334, 0x10400017, 
 0x26e50028, 0x26c40128, 0x240300ff, 0x2406ffff, 0x8ca20000, 0x24a50004, 
 0x2463ffff, 0xac820000, 0x1466fffb, 0x24840004, 0x1000000c, 0x0, 
-0x11a2000a, 0x3c050008, 0x96a7000e, 0x8ea2001c, 0x3c040001, 0x24842d20, 
-0xafb50014, 0xafa20010, 0x8ea60018, 0xc0028eb, 0x34a50910, 0x8fbf0078, 
+0x11a2000a, 0x3c050008, 0x96a7000e, 0x8ea2001c, 0x3c040001, 0x24842e80, 
+0xafb50014, 0xafa20010, 0x8ea60018, 0xc00290f, 0x34a50910, 0x8fbf0078, 
 0x8fbe0074, 0x8fb50070, 0x8fb3006c, 0x8fb10068, 0x3e00008, 0x27bd0080, 
 0x3e00008, 0x0, 0x803821, 0x8f8600e4, 0x8f8400e0, 0x2402fff8, 
 0x8cc30004, 0x822024, 0x10c4000d, 0x3c020100, 0x3c050100, 0x651024, 
@@ -4338,14 +4366,14 @@
 0xaf8800c8, 0xaf8700e4, 0xaf8700e8, 0x3e00008, 0x0, 0x27bdff70, 
 0xafbf0088, 0xafbe0084, 0xafb50080, 0xafb3007c, 0xafb10078, 0x92c200ed, 
 0xa3a0004f, 0x1040000b, 0xa3a00067, 0x8ecd00f0, 0xafad0034, 0x8ece00f4, 
-0xafae002c, 0x8ecd00fc, 0x8ed500f8, 0xafad006c, 0x8ece0100, 0x100000d9, 
-0xafae003c, 0x3c020001, 0x8c4233b8, 0x40f809, 0x27a40020, 0x1040026e, 
+0xafae002c, 0x8ecd00fc, 0x8ed500f8, 0xafad006c, 0x8ece0100, 0x100000e9, 
+0xafae003c, 0x3c020001, 0x8c423518, 0x40f809, 0x27a40020, 0x10400295, 
 0x0, 0x8fa30024, 0x8fb50020, 0x306dffff, 0x25adfffc, 0xafad0034, 
 0x92a20000, 0xafb5002c, 0x30420001, 0x10400017, 0xafa3006c, 0x8ec2011c, 
 0x3c03ffff, 0x431024, 0x14400012, 0x2402ffff, 0x8ea30000, 0x14620004, 
 0x3402ffff, 0x96a30004, 0x1062000c, 0x0, 0xc0022ad, 0x2a02021, 
-0x304200ff, 0x14400007, 0x0, 0x3c020001, 0x8c4233b0, 0x40f809, 
-0x0, 0x1000024e, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
+0x304200ff, 0x14400007, 0x0, 0x3c020001, 0x8c423510, 0x40f809, 
+0x0, 0x10000275, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
 0x431024, 0x3c03ffff, 0x432824, 0x14a00003, 0xafa20024, 0x10000053, 
 0x1821, 0x3c020080, 0xa21024, 0x50400007, 0x3c040040, 0x8ec202e4, 
 0x24420001, 0xaec202e4, 0x8ec202e4, 0x10000049, 0x24030001, 0x3c070004, 
@@ -4362,1001 +4390,1008 @@
 0x8ec20128, 0x10000006, 0x42042, 0x8ec202e0, 0x24420001, 0xaec202e0, 
 0x8ec202e0, 0x42042, 0x1488ffc6, 0x851824, 0x24030001, 0x8f420260, 
 0x8fae0034, 0x4e102b, 0x10400015, 0x306400ff, 0x8f8200e0, 0xafa20010, 
-0x8f8200e4, 0x3c040001, 0x24842dfc, 0xafa20014, 0x8fa60020, 0x8fa70024, 
-0x3c050006, 0xc0028eb, 0x34a5f003, 0x8ec30150, 0x8fad006c, 0x3c020100, 
+0x8f8200e4, 0x3c040001, 0x24842f5c, 0xafa20014, 0x8fa60020, 0x8fa70024, 
+0x3c050006, 0xc00290f, 0x34a5f003, 0x8ec30150, 0x8fad006c, 0x3c020100, 
 0x24040001, 0x1a26825, 0x24630001, 0xafad006c, 0xaec30150, 0x8ec20150, 
 0x1080000f, 0x0, 0x8f420218, 0x30420800, 0x1440000b, 0x3c020180, 
 0x8fae006c, 0x1c21024, 0x10400005, 0x0, 0x8ec20174, 0x24420001, 
-0xaec20174, 0x8ec20174, 0x100001bd, 0x8fa30034, 0x8f420218, 0x30420400, 
+0xaec20174, 0x8ec20174, 0x100001e4, 0x8fa30034, 0x8f420218, 0x30420400, 
 0x10400004, 0x0, 0x8fad0034, 0x25ad0004, 0xafad0034, 0x8ec20050, 
-0x5040001d, 0xafa0003c, 0x8fae0034, 0x4e102b, 0x50400019, 0xafa0003c, 
-0x8ec20050, 0x1c21023, 0xafa2003c, 0x8ecd0050, 0x10000013, 0xafad0034, 
-0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842e08, 0xafa20014, 
-0x8ec6003c, 0x8ec70044, 0x3c050006, 0xc0028eb, 0x34a5f002, 0x8ec202b4, 
-0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x10000172, 0x8ec202b4, 
-0x96e20460, 0x8fae0034, 0x4e102b, 0x10400004, 0x0, 0x240d0001, 
-0xa3ad004f, 0x8fae0034, 0x11c00189, 0x3c02ffff, 0x8fad006c, 0x1a21024, 
-0xafa20074, 0x8ec20068, 0x8f430280, 0x24420001, 0x304203ff, 0x1062015f, 
-0x0, 0x93a2004f, 0x10400015, 0x0, 0x8ec3005c, 0x8ec20060, 
-0x1062000a, 0x26ce0060, 0x8ec60060, 0xafae0054, 0x8ec30060, 0x21140, 
-0x24424dc0, 0x2e28821, 0x24630001, 0x10000014, 0x306300ff, 0x92c20064, 
-0x1440ffc9, 0x0, 0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, 
-0x8ec3003c, 0x8ec20044, 0x1062ffc1, 0x26cd0044, 0x8ec60044, 0xafad0054, 
-0x8ec30044, 0x21140, 0x24420dc0, 0x2e28821, 0x24630001, 0x306301ff, 
-0xafa3005c, 0x96e20462, 0x30420010, 0x1040001a, 0x340e8100, 0x96a2000c, 
-0x144e0017, 0x0, 0x92c200ed, 0x14400014, 0x0, 0x96a2000e, 
-0xa6220016, 0x8ea20008, 0x8ea30004, 0x8fad0034, 0x8ea40000, 0x25adfffc, 
-0xafad0034, 0xaea2000c, 0xaea30008, 0xaea40004, 0x9622000e, 0x8fae002c, 
-0x240d0001, 0xa3ad0067, 0x25ce0004, 0x34420200, 0xafae002c, 0xa622000e, 
-0x9627000a, 0x8fae0034, 0xee102b, 0x14400002, 0x30f3fff8, 0x8fb30034, 
-0x8e240000, 0x8e250004, 0x8fad002c, 0x24020007, 0xae2d0018, 0xafa20010, 
-0xafa60014, 0x8ec20004, 0x8fa6002c, 0xafa20018, 0x8ec200a8, 0x40f809, 
-0x2603821, 0x1440001a, 0x3c050006, 0x3c040001, 0x24842e14, 0x8e220018, 
-0x34a5f009, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x2603821, 
-0xc0028eb, 0xafa30014, 0x93a20067, 0x104000fb, 0x0, 0x8ea20004, 
-0x8ea30008, 0x8ea4000c, 0x340e8100, 0xa6ae000c, 0xaea20000, 0xaea30004, 
-0xaea40008, 0x96220016, 0x100000f0, 0xa6a2000e, 0x8fad0034, 0x166d0089, 
-0x0, 0x962e000a, 0xafae0044, 0x8fae003c, 0x9623000e, 0x1ae1021, 
-0xa622000a, 0x34620004, 0xa622000e, 0x8fad0074, 0x11a00006, 0x307effff, 
-0x34620404, 0xa622000e, 0x8fae006c, 0xe1402, 0xa6220014, 0x8ec30068, 
-0x8ee40478, 0x8ee5047c, 0x24020004, 0xafa20010, 0x8ec20068, 0x2203021, 
-0x24070020, 0xafa20014, 0x8ec20008, 0x31940, 0x604821, 0xafa20018, 
-0x8ec200a8, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809, 
-0x832021, 0x54400018, 0xa2c000ed, 0x97ad0046, 0xa63e000e, 0xa62d000a, 
-0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x24842e20, 0x3c050006, 
-0xafa20014, 0x8ec60068, 0x34a5f00b, 0xc0028eb, 0x2203821, 0x93a20067, 
-0x104000b6, 0x0, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0x340e8100, 
-0x10000083, 0xa6ae000c, 0x8fae005c, 0x8fad0054, 0xadae0000, 0x8ec202c4, 
-0x8ec30068, 0x2442ffff, 0xaec202c4, 0x8ec202c4, 0x24630001, 0x306303ff, 
-0x26c20060, 0x15a20006, 0xaec30068, 0x8ec202c0, 0x2442ffff, 0xaec202c0, 
-0x10000005, 0x8ec202c0, 0x8ec202bc, 0x2442ffff, 0xaec202bc, 0x8ec202bc, 
-0x8ec20048, 0x24420001, 0xaec20048, 0x8f430240, 0x43102b, 0x54400090, 
-0xafa00034, 0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 
-0x24020013, 0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x24070008, 
-0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 0x24842dac, 
-0xafb10010, 0xafa00014, 0x8ec60068, 0x8f470228, 0x3c050009, 0xc0028eb, 
-0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 0x370821, 
-0x1000000a, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 
-0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x8ec20268, 0x8ec2027c, 
-0x24420001, 0xaec2027c, 0x8ec2027c, 0x10000062, 0xafa00034, 0x962d000a, 
-0xafad0044, 0x9622000e, 0xa633000a, 0x8fae0074, 0x11c00006, 0x305effff, 
-0x34420400, 0xa622000e, 0x8fad006c, 0xd1402, 0xa6220014, 0x8ec30068, 
-0x8ee40478, 0x8ee5047c, 0x24020004, 0xafa20010, 0x8ec20068, 0x2203021, 
-0x24070020, 0xafa20014, 0x8ec20008, 0x31940, 0x604821, 0xafa20018, 
-0x8ec200a8, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809, 
-0x832021, 0x1440001f, 0x3c04001f, 0x97ae0046, 0xa63e000e, 0xa62e000a, 
-0x8f820100, 0xafa20010, 0x8f820104, 0x3c040001, 0x24842e20, 0x3c050006, 
-0xafa20014, 0x8ec60068, 0x34a5f00d, 0xc0028eb, 0x2203821, 0x93a20067, 
-0x10400032, 0x340d8100, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0xa6ad000c, 
-0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 0xa6a2000e, 0x9622000e, 
-0x3042fdff, 0x10000025, 0xa622000e, 0x8ec202c4, 0x8fae002c, 0x3484ffff, 
-0x1d37021, 0x2442ffff, 0xafae002c, 0xaec202c4, 0x8ec202c4, 0x8ec302bc, 
-0x24020001, 0x8e202b, 0xa2c200ed, 0x2463ffff, 0xaec302bc, 0x10800004, 
-0x8ec202bc, 0x8ec20540, 0x1c27023, 0xafae002c, 0x8fad0034, 0x8fae0054, 
-0x1b36823, 0xafad0034, 0x8fad005c, 0xadcd0000, 0x8ec20068, 0xa3a0004f, 
-0x8ec30048, 0x24420001, 0x304203ff, 0x24630001, 0xaec20068, 0xaec30048, 
-0x8fae0034, 0x15c0fe9d, 0x0, 0x8fad0034, 0x11a0001f, 0x0, 
-0xaecd00f0, 0x8fae002c, 0xaece00f4, 0xaed500f8, 0x93a20067, 0x10400004, 
-0x0, 0x8ec200f8, 0x24420004, 0xaec200f8, 0x8fad006c, 0x8ec20068, 
-0xaecd00fc, 0x8fae003c, 0xaece0100, 0x8f430280, 0x24420001, 0x304203ff, 
-0x14620006, 0x0, 0x8ec202b8, 0x24420001, 0xaec202b8, 0x10000016, 
-0x8ec202b8, 0x8ec202b0, 0x24420001, 0xaec202b0, 0x10000011, 0x8ec202b0, 
-0x8fad006c, 0x31a4ffff, 0x2484fffc, 0x801821, 0x8ec401b8, 0x8ec501bc, 
-0x3c060001, 0x8cc633b0, 0x1021, 0xa32821, 0xa3382b, 0x822021, 
-0x872021, 0xaec401b8, 0xc0f809, 0xaec501bc, 0x8fbf0088, 0x8fbe0084, 
-0x8fb50080, 0x8fb3007c, 0x8fb10078, 0x3e00008, 0x27bd0090, 0x3e00008, 
-0x0, 0x27bdff90, 0xafbf0068, 0xafbe0064, 0xafb50060, 0xafb3005c, 
-0xafb10058, 0x92c200ed, 0xafa0002c, 0x10400007, 0xa3a00037, 0x8ecf00fc, 
-0x8ec800f0, 0x8ec900f4, 0x8ed500f8, 0x100000d1, 0xafaf003c, 0x3c020001, 
-0x8c4233b8, 0x40f809, 0x27a40020, 0x104001ae, 0x0, 0x8fa30024, 
-0x8fb50020, 0x3068ffff, 0x92a20000, 0x2508fffc, 0x2a04821, 0x30420001, 
-0x1040001a, 0xafa3003c, 0x8ec2011c, 0x3c03ffff, 0x431024, 0x14400015, 
-0x2402ffff, 0x8ea30000, 0x14620005, 0x2a02021, 0x96a30004, 0x3402ffff, 
-0x1062000e, 0x0, 0xafa80048, 0xc0022ad, 0xafa9004c, 0x304200ff, 
-0x8fa80048, 0x14400007, 0x8fa9004c, 0x3c020001, 0x8c4233b0, 0x40f809, 
-0x0, 0x1000018c, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 
-0x431024, 0x3c03ffff, 0x432824, 0x14a00003, 0xafa20024, 0x10000053, 
-0x1821, 0x3c020080, 0xa21024, 0x50400007, 0x3c040040, 0x8ec202e4, 
-0x24420001, 0xaec202e4, 0x8ec202e4, 0x10000049, 0x24030001, 0x3c070004, 
-0x3c0e0001, 0x3c0d0002, 0x3c060010, 0x3c0c0008, 0x8ec20178, 0x3c0b0020, 
-0x340a8000, 0x24420001, 0xaec20178, 0x8ec20178, 0x851824, 0x10670021, 
-0xe3102b, 0x14400007, 0x0, 0x106e0011, 0x0, 0x106d0015, 
-0x0, 0x10000030, 0x42042, 0x10660023, 0xc3102b, 0x14400005, 
-0x0, 0x106c0019, 0x0, 0x10000028, 0x42042, 0x106b0021, 
-0x0, 0x10000024, 0x42042, 0x8ec2012c, 0x24420001, 0xaec2012c, 
-0x8ec2012c, 0x1000001e, 0x42042, 0x8ec202d4, 0x24420001, 0xaec202d4, 
-0x8ec202d4, 0x10000018, 0x42042, 0x8ec202d8, 0x24420001, 0xaec202d8, 
-0x8ec202d8, 0x10000012, 0x42042, 0x8ec202dc, 0x24420001, 0xaec202dc, 
-0x8ec202dc, 0x1000000c, 0x42042, 0x8ec20128, 0x24420001, 0xaec20128, 
-0x8ec20128, 0x10000006, 0x42042, 0x8ec202e0, 0x24420001, 0xaec202e0, 
-0x8ec202e0, 0x42042, 0x148affc6, 0x851824, 0x24030001, 0x8f420260, 
-0x48102b, 0x10400019, 0x306400ff, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 
-0x3c040001, 0x24842dfc, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050006, 
-0x34a5f003, 0xafa80048, 0xc0028eb, 0xafa9004c, 0x8ec30150, 0x8faf003c, 
-0x3c020100, 0x24040001, 0x1e27825, 0x24630001, 0xafaf003c, 0xaec30150, 
-0x8ec20150, 0x8fa9004c, 0x8fa80048, 0x10800025, 0x0, 0x8f420218, 
-0x30420800, 0x14400021, 0x3c020180, 0x8faf003c, 0x1e21024, 0x104000fe, 
-0x1001821, 0x8ec20174, 0x24420001, 0xaec20174, 0x8ec20174, 0x100000f8, 
-0x1001821, 0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842e08, 
-0xafa20014, 0x8ec6003c, 0x8ec70044, 0x3c050006, 0x34a5f002, 0xafa80048, 
-0xc0028eb, 0xafa9004c, 0x8ec202b4, 0x2403ffbf, 0x283a024, 0x24420001, 
-0xaec202b4, 0x8ec202b4, 0x8fa80048, 0x100000c2, 0x8fa9004c, 0x8f420218, 
-0x30420400, 0x54400001, 0x25080004, 0x96e20460, 0x48102b, 0x10400003, 
-0x0, 0x3c0f8000, 0xafaf002c, 0x110000d2, 0x3c02ffff, 0x8faf003c, 
-0x1e21024, 0xafa20044, 0x8ec20068, 0x8f430280, 0x24420001, 0x304203ff, 
-0x106200ad, 0x0, 0x8faf002c, 0x11e00014, 0x0, 0x8ec3005c, 
-0x8ec20060, 0x10620009, 0x26cb0060, 0x8ec60060, 0x8ec30060, 0x21140, 
-0x24424dc0, 0x2e28821, 0x24630001, 0x10000014, 0x306a00ff, 0x92c20064, 
-0x1440ffc4, 0x0, 0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, 
-0x8ec3003c, 0x8ec20044, 0x1062ffbc, 0x26cb0044, 0x8ec60044, 0xafa0002c, 
-0x8ec30044, 0x21140, 0x24420dc0, 0x2e28821, 0x24630001, 0x306a01ff, 
-0x96e20462, 0x30420010, 0x10400017, 0x0, 0x96a2000c, 0x340f8100, 
-0x144f0013, 0x0, 0x92c200ed, 0x14400010, 0x0, 0x96a2000e, 
-0xa6220016, 0x8ea20008, 0x8ea30004, 0x8ea40000, 0x2508fffc, 0xaea2000c, 
-0xaea30008, 0xaea40004, 0x9622000e, 0x25290004, 0x240f0001, 0xa3af0037, 
-0x34420200, 0xa622000e, 0x9623000a, 0x68102b, 0x14400002, 0x3073fff8, 
-0x1009821, 0x92c300ed, 0x2e62003d, 0x2c630001, 0x621824, 0x1060000f, 
-0x260f021, 0x9523000c, 0x24020800, 0x5462000c, 0xae290018, 0x91220017, 
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600004, 
-0xae290018, 0x95220010, 0x245e000e, 0xae290018, 0x92c300ed, 0x8e240000, 
-0x8e250004, 0x8faf002c, 0x2402000b, 0xafa20010, 0x3182b, 0x31ec0, 
-0xcf1025, 0x431025, 0xafa20014, 0x8ec20004, 0xafa20018, 0x8ec200a8, 
-0x3c03821, 0x1203021, 0xafa80048, 0xafa9004c, 0xafaa0050, 0x40f809, 
-0xafab0054, 0x8fa80048, 0x8fa9004c, 0x8faa0050, 0x8fab0054, 0x1440001d, 
-0x3c050006, 0x3c040001, 0x24842e14, 0x8e220018, 0x34a5f009, 0xafa20010, 
-0x8e220000, 0x8e230004, 0x2203021, 0x3c03821, 0xafa80048, 0xafa9004c, 
-0xc0028eb, 0xafa30014, 0x93a20037, 0x8fa80048, 0x8fa9004c, 0x1040002a, 
-0x340f8100, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0xa6af000c, 0xaea20000, 
-0xaea30004, 0xaea40008, 0x96220016, 0x10000020, 0xa6a2000e, 0x8faf0044, 
-0x11e00007, 0x0, 0x8faf003c, 0x9623000e, 0xf1402, 0x34630400, 
-0xa6220014, 0xa623000e, 0x56680008, 0x1334821, 0x9622000e, 0xa628000a, 
-0x4021, 0x34420004, 0xa622000e, 0x1000000c, 0xa2c000ed, 0x3c03001f, 
-0x3463ffff, 0x24020001, 0x69182b, 0xa633000a, 0x10600003, 0xa2c200ed, 
-0x8ec20540, 0x1224823, 0x1134023, 0xafa0002c, 0x1500ff4f, 0xad6a0000, 
-0x1100001b, 0x0, 0xaec800f0, 0xaec900f4, 0xaed500f8, 0x93a20037, 
-0x10400004, 0x0, 0x8ec200f8, 0x24420004, 0xaec200f8, 0x8faf003c, 
-0x8ec20068, 0xaecf00fc, 0x8f430280, 0x24420001, 0x14620006, 0x0, 
-0x8ec202b8, 0x24420001, 0xaec202b8, 0x10000016, 0x8ec202b8, 0x8ec202b0, 
-0x24420001, 0xaec202b0, 0x10000011, 0x8ec202b0, 0x8faf003c, 0x31e4ffff, 
-0x2484fffc, 0x801821, 0x8ec401b8, 0x8ec501bc, 0x3c060001, 0x8cc633b0, 
-0x1021, 0xa32821, 0xa3382b, 0x822021, 0x872021, 0xaec401b8, 
-0xc0f809, 0xaec501bc, 0x8fbf0068, 0x8fbe0064, 0x8fb50060, 0x8fb3005c, 
-0x8fb10058, 0x3e00008, 0x27bd0070, 0x3e00008, 0x0, 0x27bdffd8, 
-0xafbf0024, 0xafb10020, 0x8ec30040, 0x8ec20038, 0x1062004d, 0x0, 
-0x8ec30038, 0x8ec20040, 0x623823, 0x4e20001, 0x24e70200, 0x8ec30044, 
-0x8ec20040, 0x43102b, 0x14400004, 0x24020200, 0x8ec30040, 0x10000005, 
-0x431823, 0x8ec20044, 0x8ec30040, 0x431023, 0x2443ffff, 0xe08821, 
-0x71102a, 0x54400001, 0x608821, 0x8ec90040, 0x8ee40458, 0x8ee5045c, 
-0x8ec60040, 0x113940, 0x24080002, 0xafa80010, 0x8ec80040, 0x94940, 
-0x1201821, 0x1021, 0xafa80014, 0x8ec80010, 0xa32821, 0xa3482b, 
-0x822021, 0x892021, 0x63140, 0xafa80018, 0x8ec200a4, 0x24c60dc0, 
-0x40f809, 0x2e63021, 0x1440000e, 0x24030040, 0x8ec20040, 0xafa20010, 
-0x8ec20044, 0x3c040001, 0x24842e2c, 0xafa20014, 0x8ec60038, 0x8ec7003c, 
-0x3c050007, 0xc0028eb, 0x34a5f001, 0x10000010, 0x0, 0x8ec20030, 
-0x24420001, 0x50430003, 0x1021, 0x8ec20030, 0x24420001, 0xaec20030, 
-0x8ec20030, 0x21080, 0x571021, 0xac510cc0, 0x8ec20040, 0x511021, 
-0x304201ff, 0xaec20040, 0x8ec30040, 0x8ec20038, 0x14620017, 0x0, 
-0x8ec20000, 0x10400007, 0x2403fdff, 0xaf80004c, 0x8f82004c, 0x1040fffd, 
-0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 
-0x0, 0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003, 
-0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020, 
-0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 
-0xafb10020, 0x8ec30058, 0x8ec20054, 0x1062004d, 0x0, 0x8ec30054, 
-0x8ec20058, 0x623823, 0x4e20001, 0x24e70100, 0x8ec30060, 0x8ec20058, 
-0x43102b, 0x14400004, 0x24020100, 0x8ec30058, 0x10000005, 0x431823, 
-0x8ec20060, 0x8ec30058, 0x431023, 0x2443ffff, 0xe08821, 0x71102a, 
-0x54400001, 0x608821, 0x8ec90058, 0x8ee40468, 0x8ee5046c, 0x8ec60058, 
-0x113940, 0x24080003, 0xafa80010, 0x8ec80058, 0x94940, 0x1201821, 
-0x1021, 0xafa80014, 0x8ec80010, 0xa32821, 0xa3482b, 0x822021, 
-0x892021, 0x63140, 0xafa80018, 0x8ec200a4, 0x24c64dc0, 0x40f809, 
-0x2e63021, 0x1440000e, 0x24030040, 0x8ec20058, 0xafa20010, 0x8ec20060, 
-0x3c040001, 0x24842e38, 0xafa20014, 0x8ec60054, 0x8ec7005c, 0x3c050007, 
-0xc0028eb, 0x34a5f010, 0x10000010, 0x0, 0x8ec20030, 0x24420001, 
-0x50430003, 0x1021, 0x8ec20030, 0x24420001, 0xaec20030, 0x8ec20030, 
-0x21080, 0x571021, 0xac510cc0, 0x8ec20058, 0x511021, 0x304200ff, 
-0xaec20058, 0x8ec30058, 0x8ec20054, 0x14620017, 0x0, 0x8ec20000, 
-0x10400007, 0x2403feff, 0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 
-0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 
-0x8f820060, 0x431024, 0xaf820060, 0x8ec20000, 0x10400003, 0x0, 
-0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008, 
-0x27bd0028, 0x3e00008, 0x0, 0x8f820120, 0x8ec300e8, 0x8f820124, 
-0x8f860128, 0x24020040, 0x24630001, 0x50620003, 0x1021, 0x8ec200e8, 
-0x24420001, 0xaec200e8, 0x8ec200e8, 0x8ec400e8, 0x8ec300e4, 0x210c0, 
-0x24426fc0, 0x14830007, 0x2e22821, 0x8f820128, 0x24420020, 0xaf820128, 
-0x8f820128, 0x10000011, 0xaca00000, 0x8ec200e8, 0x24030040, 0x24420001, 
-0x50430003, 0x1021, 0x8ec200e8, 0x24420001, 0x220c0, 0x2e41021, 
-0x8c426fc4, 0x8f830128, 0x21140, 0x621821, 0x2e41021, 0xaf830128, 
-0xac406fc0, 0x8cc20018, 0x2443fffe, 0x2c620018, 0x1040000a, 0x31080, 
-0x3c010001, 0x220821, 0x8c222e48, 0x400008, 0x0, 0x24020001, 
-0x3c010001, 0x370821, 0xac2281e8, 0x3e00008, 0x0, 0x3e00008, 
-0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, 
-0xafb10040, 0x8f830128, 0x8f820124, 0x106201e1, 0x0, 0x8f9e0128, 
-0x8f820128, 0x24420020, 0xaf820128, 0x8fc40018, 0x8f820128, 0x2402000b, 
-0x1482018f, 0x24020002, 0x8fc3001c, 0x97c20016, 0x3064ffff, 0xafc20014, 
-0x3c028000, 0x621024, 0xafc4001c, 0xafa2002c, 0x8fab002c, 0x3c020800, 
-0x11600004, 0x622824, 0x41140, 0x10000003, 0x24424dc0, 0x41140, 
-0x24420dc0, 0x2e2a821, 0x96a2000e, 0x3043fffc, 0x30420400, 0x10400003, 
-0xa6a3000e, 0x10000137, 0x8821, 0x10a00004, 0x8821, 0x97d10016, 
-0x10000132, 0x0, 0x8eab0018, 0xafab0034, 0x9563000c, 0x96eb0462, 
-0x24020800, 0x1462012b, 0xafab003c, 0x8fab0034, 0x2573000e, 0x8fab003c, 
-0x31620002, 0x1040003f, 0x3c030020, 0x8ec70540, 0x263102b, 0x14400002, 
-0x2604821, 0x2674823, 0x25220014, 0x43102b, 0x10400027, 0x24030005, 
-0x91220000, 0x3042000f, 0x14430024, 0x1202021, 0x952a0000, 0x25290002, 
-0x95280000, 0x25290002, 0x95270000, 0x25290002, 0x95260000, 0x25290002, 
-0x95250000, 0x25290002, 0x95230000, 0x25290002, 0x95220000, 0x25290002, 
-0x95240000, 0x25290002, 0x1485021, 0x1475021, 0x1465021, 0x1455021, 
-0x1435021, 0x1425021, 0x95220000, 0x95230002, 0x1445021, 0x1425021, 
-0x1435021, 0xa1c02, 0x3142ffff, 0x625021, 0xa1c02, 0x3142ffff, 
-0x10000009, 0x625021, 0x1202021, 0x90850000, 0x3c060020, 0x8ec200ac, 
-0x30a5000f, 0x40f809, 0x52840, 0x304affff, 0x3143ffff, 0x50600001, 
-0x3403ffff, 0x96a2000e, 0x34420002, 0x10000002, 0xa6a2000e, 0x1821, 
-0xa6a30010, 0x8fab003c, 0x31620001, 0x104000e1, 0x0, 0x92620009, 
-0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x106000d9, 
-0x3c030020, 0x8fa60034, 0x8ec70540, 0xc3102b, 0x50400001, 0xc73023, 
-0x24c2000e, 0x43102b, 0x1040001a, 0xc02021, 0x94c70000, 0x24c60002, 
-0x94c50000, 0x24c60002, 0x94c30000, 0x24c60002, 0x94c20000, 0x24c60002, 
-0x94c40000, 0x24c60002, 0xe53821, 0xe33821, 0xe23821, 0x94c20000, 
-0x94c30002, 0xe43821, 0xe23821, 0xe33821, 0x71c02, 0x30e2ffff, 
-0x623821, 0x71c02, 0x30e2ffff, 0x10000006, 0x623821, 0x8ec200ac, 
-0x24050007, 0x40f809, 0x3c060020, 0x3047ffff, 0x8fab003c, 0x31620008, 
-0x10400003, 0x30e8ffff, 0x1000005b, 0x4821, 0x96620006, 0x30421fff, 
-0x10400007, 0x2602821, 0x92620000, 0x96630002, 0x3042000f, 0x21080, 
-0x10000051, 0x624823, 0x3c070020, 0x8ec30540, 0xa7102b, 0x50400001, 
-0xa32823, 0x24a20014, 0x47102b, 0x10400015, 0xa02021, 0x90a20000, 
-0x94a30002, 0x3042000f, 0x21080, 0x623023, 0xafa20020, 0x90a30009, 
-0x24a5000c, 0x94a20000, 0x24a50002, 0x94a40000, 0x24a50002, 0xc33021, 
-0xc23021, 0x94a20000, 0x94a30002, 0xc43021, 0xc23021, 0x1000002d, 
-0xc33021, 0x24a50002, 0xa7102b, 0x50400001, 0xa32823, 0x94a60000, 
-0x802821, 0xa7102b, 0x50400001, 0xa32823, 0x90a20000, 0x24850009, 
-0x3042000f, 0x21080, 0xc23023, 0xafa20020, 0xa7102b, 0x50400001, 
-0xa32823, 0x90a20000, 0x2485000c, 0xc23021, 0xa7102b, 0x50400001, 
-0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001, 
-0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001, 
-0xa32823, 0x94a20000, 0x24a50002, 0xc23021, 0xa7102b, 0x50400001, 
-0xa32823, 0x94a20000, 0xc23021, 0x61c02, 0x30c2ffff, 0x623021, 
-0x61402, 0x30c3ffff, 0x431021, 0x3049ffff, 0x96a2000e, 0x30420004, 
-0x10400041, 0x0, 0x8f420218, 0x30420400, 0x1040003d, 0x3c070020, 
-0x97c2000e, 0x8fc30008, 0x8ec60540, 0x621821, 0x2463fffc, 0x67102b, 
-0x50400001, 0x661823, 0x602821, 0x24a20004, 0x47102b, 0x5040000a, 
-0xa7102b, 0x90a20000, 0x90a40001, 0x90a30002, 0x21200, 0x441021, 
-0x90a40003, 0x31a00, 0x10000017, 0x431021, 0x50400001, 0xa62823, 
-0x90a20000, 0x24a50001, 0x22200, 0xa7102b, 0x50400001, 0xa62823, 
-0x90a20000, 0x24a50001, 0x822021, 0xa7102b, 0x50400001, 0xa62823, 
-0x90a20000, 0x24a50001, 0x21200, 0x822021, 0xa7102b, 0x50400001, 
-0xa62823, 0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 
-0x41402, 0x3083ffff, 0x431021, 0x3042ffff, 0x1024021, 0x81c02, 
-0x3102ffff, 0x624021, 0x81c02, 0x3102ffff, 0x624021, 0x3108ffff, 
-0x8fc20014, 0x488823, 0x111402, 0x2228821, 0x2298821, 0x111402, 
-0x2228821, 0x3231ffff, 0x52200001, 0x3411ffff, 0x96a2000e, 0x34420001, 
-0xa6a2000e, 0x96a2000e, 0x24080002, 0x30420004, 0x10400002, 0xa6b10012, 
-0x24080004, 0x8ec90068, 0x8ee40478, 0x8ee5047c, 0xafa80010, 0x8ec80068, 
-0x8fab002c, 0x2a03021, 0x24070020, 0x10b4025, 0xafa80014, 0x8ec80008, 
-0x94940, 0x1201821, 0xafa80018, 0x8ec800a8, 0x1021, 0xa32821, 
-0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000e, 0x0, 
-0x8f820120, 0xafa20010, 0x8f820128, 0x3c040001, 0x24842ea8, 0xafa20014, 
-0x8fc6001c, 0x8f870124, 0x3c050008, 0xc0028eb, 0x34a50001, 0x1000005f, 
-0x0, 0x8ec20068, 0x24420001, 0x304203ff, 0xaec20068, 0x8fab002c, 
-0x11600006, 0x0, 0x8ec202c0, 0x2442ffff, 0xaec202c0, 0x10000005, 
-0x8ec202c0, 0x8ec202bc, 0x2442ffff, 0xaec202bc, 0x8ec202bc, 0x8ec202c4, 
-0x2442ffff, 0xaec202c4, 0x1000004a, 0x8ec202c4, 0x14820005, 0x24020004, 
-0x8ec20048, 0x24420001, 0x10000044, 0xaec20048, 0x14820036, 0x38830011, 
-0x97c2001e, 0xafc2001c, 0x8ec20048, 0x24420001, 0xaec20048, 0x8f430240, 
-0x43102b, 0x14400039, 0x24070008, 0x8ed10068, 0x8ee40490, 0x8ee50494, 
-0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014, 0xafa30018, 
-0x8ec200a8, 0x40f809, 0x24c6001c, 0x1440000b, 0x24020001, 0x3c040001, 
-0x24842dac, 0xafb10010, 0xafa00014, 0x8ec60068, 0x8f470228, 0x3c050009, 
-0xc0028eb, 0x34a5f008, 0x1021, 0x14400005, 0x24020001, 0x3c010001, 
-0x370821, 0x1000000a, 0xac2281e0, 0x3c010001, 0x370821, 0xac2081e0, 
-0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001, 0xaec20268, 0x8ec20268, 
-0x8ec2027c, 0x24420001, 0xaec2027c, 0x1000000d, 0x8ec2027c, 0x2c630001, 
-0x38820013, 0x2c420001, 0x621825, 0x14600004, 0x24020001, 0x24020012, 
-0x14820004, 0x24020001, 0x3c010001, 0x370821, 0xac2281e8, 0x8fbf0050, 
-0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb10040, 0x3e00008, 0x27bd0058, 
-0x3e00008, 0x0, 0x0, 0x0, 0x8ec20538, 0xaf8200c0, 
-0x8ec20538, 0xaf8200c4, 0x8ec20538, 0xaf8200c8, 0x8ec20534, 0xaf8200d0, 
-0x8ec20534, 0xaf8200d4, 0x8ec20534, 0x3e00008, 0xaf8200d8, 0x27bdffe8, 
-0x27840208, 0x27450200, 0xafbf0010, 0xc00297e, 0x24060008, 0x8f420204, 
-0xc003c3a, 0xaf820210, 0x24040001, 0x8f460248, 0x24020004, 0x3c010001, 
-0xac2232ac, 0xc004680, 0x24050004, 0x3c020001, 0x8c4232a8, 0x30420001, 
-0x10400007, 0x24020001, 0x3c010001, 0xac2232ac, 0x24040001, 0x24050001, 
-0xc004680, 0x3c06601b, 0x8ec20548, 0x8ec4054c, 0x8ec30550, 0x3c010001, 
-0xac2032a4, 0x3c010001, 0xac2032bc, 0x21640, 0x42140, 0x34840403, 
-0x441025, 0x31bc0, 0x431025, 0xaf82021c, 0x8fbf0010, 0x3e00008, 
-0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 
-0xafa00014, 0x8f860200, 0x3c040001, 0x24842f7c, 0xc0028eb, 0x3821, 
-0x8ec20368, 0x24420001, 0xaec20368, 0x8ec20368, 0x8f830200, 0x3c023f00, 
-0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 
-0xafbf0020, 0xafb3001c, 0xafb10018, 0x8f910220, 0x8ec202fc, 0x24420001, 
-0xaec202fc, 0x8ec202fc, 0x8ec30310, 0x3c020001, 0x8c4232bc, 0x3c040001, 
-0x24842f88, 0xafa20014, 0xafa30010, 0x8ec70314, 0x3c050008, 0xc0028eb, 
-0x2203021, 0x3c024000, 0x2221024, 0x104000e5, 0x3c040100, 0x8ec20314, 
-0x24420001, 0xaec20314, 0x8ec20314, 0x8f820220, 0x3c0308ff, 0x3463ffff, 
-0x431024, 0x34420004, 0xaf820220, 0x8f8200e0, 0x8f8300c4, 0x3c02001f, 
-0x3442ffff, 0x24690008, 0x49102b, 0x10400003, 0x0, 0x8ec20540, 
-0x1224823, 0x8f8700c8, 0x8f850120, 0x8f840124, 0x10000005, 0x5821, 
-0x8ec20534, 0x82102b, 0x50400001, 0x27644800, 0x10a40010, 0x316200ff, 
-0x8c820018, 0x38430007, 0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 
-0x5060fff3, 0x24840020, 0x8ec20328, 0x240b0001, 0x24420001, 0xaec20328, 
-0x8ec20328, 0x8c870008, 0x316200ff, 0x14400078, 0x0, 0x92c200ed, 
-0x14400075, 0x0, 0x8f8500e4, 0x8f8200e0, 0x2403fff8, 0x433024, 
-0xc51023, 0x218c3, 0x4620001, 0x24630100, 0x8f8a00c4, 0x10600005, 
-0x24020001, 0x10620009, 0x0, 0x10000021, 0x0, 0x8ec20318, 
-0x1403821, 0x24420001, 0xaec20318, 0x10000060, 0x8ec20318, 0x8ec2031c, 
-0x24420001, 0xaec2031c, 0x8ca70000, 0x8ec20540, 0x8ec3031c, 0x1471823, 
-0x43102b, 0x10400004, 0x2c62233f, 0x8ec20540, 0x621821, 0x2c62233f, 
-0x14400051, 0x3c020100, 0xaca20004, 0x8f8200e8, 0x24420008, 0xaf8200e8, 
-0x8f8200e8, 0x8f8200e4, 0x1403821, 0x24420008, 0xaf8200e4, 0x10000046, 
-0x8f8200e4, 0x8ec20320, 0x24420001, 0xaec20320, 0x8ca80000, 0x8ec20540, 
-0x8ec30320, 0x1092023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 
-0x822021, 0x8ec20544, 0x44102b, 0x10400003, 0x3c030100, 0x10000034, 
-0x1003821, 0x8ca20004, 0x431025, 0xaca20004, 0x8f8200e4, 0x24450008, 
-0xaf8500e4, 0x8f8500e4, 0x10a60025, 0x3c080100, 0x8ec20174, 0x24420001, 
-0xaec20174, 0x8ca20004, 0x8ec30174, 0x481024, 0x1440000e, 0x0, 
-0x8ca30000, 0x8ec20540, 0x692023, 0x44102b, 0x10400003, 0x0, 
-0x8ec20540, 0x822021, 0x8ec20544, 0x44102b, 0x10400006, 0x0, 
-0x603821, 0x8ec20544, 0x44102b, 0x1440000a, 0x0, 0x8ca20004, 
-0x481025, 0xaca20004, 0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, 
-0x14a6ffdf, 0x0, 0x14a60005, 0x0, 0x1403821, 0xaf8600e4, 
-0x10000003, 0xaf8600e8, 0xaf8500e4, 0xaf8500e8, 0x8f8300c8, 0x8ec20540, 
-0x692023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, 
-0x8ec20544, 0x82102b, 0x50400008, 0x5821, 0x8ec20540, 0xe92023, 
+0x5040002d, 0xafa0003c, 0x8fae0034, 0x4e102b, 0x50400029, 0xafa0003c, 
+0x8ec20050, 0x1c21023, 0xafa2003c, 0x8ecd0050, 0x10000023, 0xafad0034, 
+0x8ec2005c, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842f68, 0xafa20014, 
+0x8ec6003c, 0x8ec70044, 0x3c050006, 0xc00290f, 0x34a5f002, 0x8ec202b4, 
+0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x10000199, 0x8ec202b4, 
+0x8e220018, 0x8fa70034, 0x3c040001, 0x24842f74, 0xafa20010, 0x8e220000, 
+0x8e230004, 0x34a5f709, 0x2203021, 0xc00290f, 0xafa30014, 0x8ec20298, 
+0x24420001, 0xaec20298, 0x10000189, 0x8ec20298, 0x96e20460, 0x8fae0034, 
+0x4e102b, 0x10400004, 0x0, 0x240d0001, 0xa3ad004f, 0x8fae0034, 
+0x11c001a0, 0x3c02ffff, 0x8fad006c, 0x1a21024, 0xafa20074, 0x8ec20068, 
+0x8f430280, 0x24420001, 0x304203ff, 0x10620176, 0x0, 0x93a2004f, 
+0x10400015, 0x0, 0x8ec3005c, 0x8ec20060, 0x1062000a, 0x26ce0060, 
+0x8ec60060, 0xafae0054, 0x8ec30060, 0x21140, 0x24424dc0, 0x2e28821, 
+0x24630001, 0x10000014, 0x306300ff, 0x92c20064, 0x1440ffb9, 0x0, 
+0x8ec202c8, 0x24420001, 0xaec202c8, 0x8ec202c8, 0x8ec3003c, 0x8ec20044, 
+0x1062ffb1, 0x26cd0044, 0x8ec60044, 0xafad0054, 0x8ec30044, 0x21140, 
+0x24420dc0, 0x2e28821, 0x24630001, 0x306301ff, 0xafa3005c, 0x8f83012c, 
+0x10600011, 0x24040002, 0x8f820124, 0x431023, 0x21143, 0x58400001, 
+0x24420040, 0x82102a, 0x1040000a, 0x1021, 0x8f820128, 0x431023, 
+0x21143, 0x58400001, 0x24420040, 0x82102a, 0x14400002, 0x24020001, 
+0x1021, 0x304200ff, 0x1040ffa3, 0x3c050006, 0x96e20462, 0x30420010, 
+0x1040001a, 0x340e8100, 0x96a2000c, 0x144e0017, 0x0, 0x92c200ed, 
+0x14400014, 0x0, 0x96a2000e, 0xa6220016, 0x8ea20008, 0x8ea30004, 
+0x8fad0034, 0x8ea40000, 0x25adfffc, 0xafad0034, 0xaea2000c, 0xaea30008, 
+0xaea40004, 0x9622000e, 0x8fae002c, 0x240d0001, 0xa3ad0067, 0x25ce0004, 
+0x34420200, 0xafae002c, 0xa622000e, 0x9627000a, 0x8fae0034, 0xee102b, 
+0x14400002, 0x30f3fff8, 0x8fb30034, 0x8e240000, 0x8e250004, 0x8fad002c, 
+0x24020007, 0xae2d0018, 0xafa20010, 0xafa60014, 0x8ec20004, 0x8fa6002c, 
+0xafa20018, 0x8ec200a8, 0x40f809, 0x2603821, 0x1440001a, 0x3c050006, 
+0x3c040001, 0x24842f80, 0x8e220018, 0x34a5f009, 0xafa20010, 0x8e220000, 
+0x8e230004, 0x2203021, 0x2603821, 0xc00290f, 0xafa30014, 0x93a20067, 
+0x104000fb, 0x0, 0x8ea20004, 0x8ea30008, 0x8ea4000c, 0x340e8100, 
+0xa6ae000c, 0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 0x100000f0, 
+0xa6a2000e, 0x8fad0034, 0x166d0089, 0x0, 0x962e000a, 0xafae0044, 
+0x8fae003c, 0x9623000e, 0x1ae1021, 0xa622000a, 0x34620004, 0xa622000e, 
+0x8fad0074, 0x11a00006, 0x307effff, 0x34620404, 0xa622000e, 0x8fae006c, 
+0xe1402, 0xa6220014, 0x8ec30068, 0x8ee40478, 0x8ee5047c, 0x24020004, 
+0xafa20010, 0x8ec20068, 0x2203021, 0x24070020, 0xafa20014, 0x8ec20008, 
+0x31940, 0x604821, 0xafa20018, 0x8ec200a8, 0x4021, 0xa92821, 
+0xa9182b, 0x882021, 0x40f809, 0x832021, 0x54400018, 0xa2c000ed, 
+0x97ad0046, 0xa63e000e, 0xa62d000a, 0x8f820100, 0xafa20010, 0x8f820104, 
+0x3c040001, 0x24842f8c, 0x3c050006, 0xafa20014, 0x8ec60068, 0x34a5f00b, 
+0xc00290f, 0x2203821, 0x93a20067, 0x104000b6, 0x0, 0x8ea20004, 
+0x8ea30008, 0x8ea4000c, 0x340e8100, 0x10000083, 0xa6ae000c, 0x8fae005c, 
+0x8fad0054, 0xadae0000, 0x8ec202c4, 0x8ec30068, 0x2442ffff, 0xaec202c4, 
+0x8ec202c4, 0x24630001, 0x306303ff, 0x26c20060, 0x15a20006, 0xaec30068, 
+0x8ec202c0, 0x2442ffff, 0xaec202c0, 0x10000005, 0x8ec202c0, 0x8ec202bc, 
+0x2442ffff, 0xaec202bc, 0x8ec202bc, 0x8ec20048, 0x24420001, 0xaec20048, 
+0x8f430240, 0x43102b, 0x54400090, 0xafa00034, 0x8ed10068, 0x8ee40490, 
+0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, 0xafa20010, 0xafb10014, 
+0xafa30018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440000b, 
+0x24020001, 0x3c040001, 0x24842f0c, 0xafb10010, 0xafa00014, 0x8ec60068, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, 0x14400005, 
+0x24020001, 0x3c010001, 0x370821, 0x1000000a, 0xac2281e0, 0x3c010001, 
+0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, 0x24420001, 
+0xaec20268, 0x8ec20268, 0x8ec2027c, 0x24420001, 0xaec2027c, 0x8ec2027c, 
+0x10000062, 0xafa00034, 0x962d000a, 0xafad0044, 0x9622000e, 0xa633000a, 
+0x8fae0074, 0x11c00006, 0x305effff, 0x34420400, 0xa622000e, 0x8fad006c, 
+0xd1402, 0xa6220014, 0x8ec30068, 0x8ee40478, 0x8ee5047c, 0x24020004, 
+0xafa20010, 0x8ec20068, 0x2203021, 0x24070020, 0xafa20014, 0x8ec20008, 
+0x31940, 0x604821, 0xafa20018, 0x8ec200a8, 0x4021, 0xa92821, 
+0xa9182b, 0x882021, 0x40f809, 0x832021, 0x1440001f, 0x3c04001f, 
+0x97ae0046, 0xa63e000e, 0xa62e000a, 0x8f820100, 0xafa20010, 0x8f820104, 
+0x3c040001, 0x24842f8c, 0x3c050006, 0xafa20014, 0x8ec60068, 0x34a5f00d, 
+0xc00290f, 0x2203821, 0x93a20067, 0x10400032, 0x340d8100, 0x8ea20004, 
+0x8ea30008, 0x8ea4000c, 0xa6ad000c, 0xaea20000, 0xaea30004, 0xaea40008, 
+0x96220016, 0xa6a2000e, 0x9622000e, 0x3042fdff, 0x10000025, 0xa622000e, 
+0x8ec202c4, 0x8fae002c, 0x3484ffff, 0x1d37021, 0x2442ffff, 0xafae002c, 
+0xaec202c4, 0x8ec202c4, 0x8ec302bc, 0x24020001, 0x8e202b, 0xa2c200ed, 
+0x2463ffff, 0xaec302bc, 0x10800004, 0x8ec202bc, 0x8ec20540, 0x1c27023, 
+0xafae002c, 0x8fad0034, 0x8fae0054, 0x1b36823, 0xafad0034, 0x8fad005c, 
+0xadcd0000, 0x8ec20068, 0xa3a0004f, 0x8ec30048, 0x24420001, 0x304203ff, 
+0x24630001, 0xaec20068, 0xaec30048, 0x8fae0034, 0x15c0fe86, 0x0, 
+0x8fad0034, 0x11a0001f, 0x0, 0xaecd00f0, 0x8fae002c, 0xaece00f4, 
+0xaed500f8, 0x93a20067, 0x10400004, 0x0, 0x8ec200f8, 0x24420004, 
+0xaec200f8, 0x8fad006c, 0x8ec20068, 0xaecd00fc, 0x8fae003c, 0xaece0100, 
+0x8f430280, 0x24420001, 0x304203ff, 0x14620006, 0x0, 0x8ec202b8, 
+0x24420001, 0xaec202b8, 0x10000016, 0x8ec202b8, 0x8ec202b0, 0x24420001, 
+0xaec202b0, 0x10000011, 0x8ec202b0, 0x8fad006c, 0x31a4ffff, 0x2484fffc, 
+0x801821, 0x8ec401b8, 0x8ec501bc, 0x3c060001, 0x8cc63510, 0x1021, 
+0xa32821, 0xa3382b, 0x822021, 0x872021, 0xaec401b8, 0xc0f809, 
+0xaec501bc, 0x8fbf0088, 0x8fbe0084, 0x8fb50080, 0x8fb3007c, 0x8fb10078, 
+0x3e00008, 0x27bd0090, 0x3e00008, 0x0, 0x27bdff90, 0xafbf0068, 
+0xafbe0064, 0xafb50060, 0xafb3005c, 0xafb10058, 0x92c200ed, 0xafa0002c, 
+0x10400007, 0xa3a00037, 0x8ecf00fc, 0x8ec800f0, 0x8ec900f4, 0x8ed500f8, 
+0x100000d1, 0xafaf003c, 0x3c020001, 0x8c423518, 0x40f809, 0x27a40020, 
+0x104001ae, 0x0, 0x8fa30024, 0x8fb50020, 0x3068ffff, 0x92a20000, 
+0x2508fffc, 0x2a04821, 0x30420001, 0x1040001a, 0xafa3003c, 0x8ec2011c, 
+0x3c03ffff, 0x431024, 0x14400015, 0x2402ffff, 0x8ea30000, 0x14620005, 
+0x2a02021, 0x96a30004, 0x3402ffff, 0x1062000e, 0x0, 0xafa80048, 
+0xc0022ad, 0xafa9004c, 0x304200ff, 0x8fa80048, 0x14400007, 0x8fa9004c, 
+0x3c020001, 0x8c423510, 0x40f809, 0x0, 0x1000018c, 0x0, 
+0x8fa20024, 0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff, 0x432824, 
+0x14a00003, 0xafa20024, 0x10000053, 0x1821, 0x3c020080, 0xa21024, 
+0x50400007, 0x3c040040, 0x8ec202e4, 0x24420001, 0xaec202e4, 0x8ec202e4, 
+0x10000049, 0x24030001, 0x3c070004, 0x3c0e0001, 0x3c0d0002, 0x3c060010, 
+0x3c0c0008, 0x8ec20178, 0x3c0b0020, 0x340a8000, 0x24420001, 0xaec20178, 
+0x8ec20178, 0x851824, 0x10670021, 0xe3102b, 0x14400007, 0x0, 
+0x106e0011, 0x0, 0x106d0015, 0x0, 0x10000030, 0x42042, 
+0x10660023, 0xc3102b, 0x14400005, 0x0, 0x106c0019, 0x0, 
+0x10000028, 0x42042, 0x106b0021, 0x0, 0x10000024, 0x42042, 
+0x8ec2012c, 0x24420001, 0xaec2012c, 0x8ec2012c, 0x1000001e, 0x42042, 
+0x8ec202d4, 0x24420001, 0xaec202d4, 0x8ec202d4, 0x10000018, 0x42042, 
+0x8ec202d8, 0x24420001, 0xaec202d8, 0x8ec202d8, 0x10000012, 0x42042, 
+0x8ec202dc, 0x24420001, 0xaec202dc, 0x8ec202dc, 0x1000000c, 0x42042, 
+0x8ec20128, 0x24420001, 0xaec20128, 0x8ec20128, 0x10000006, 0x42042, 
+0x8ec202e0, 0x24420001, 0xaec202e0, 0x8ec202e0, 0x42042, 0x148affc6, 
+0x851824, 0x24030001, 0x8f420260, 0x48102b, 0x10400019, 0x306400ff, 
+0x8f8200e0, 0xafa20010, 0x8f8200e4, 0x3c040001, 0x24842f5c, 0xafa20014, 
+0x8fa60020, 0x8fa70024, 0x3c050006, 0x34a5f003, 0xafa80048, 0xc00290f, 
+0xafa9004c, 0x8ec30150, 0x8faf003c, 0x3c020100, 0x24040001, 0x1e27825, 
+0x24630001, 0xafaf003c, 0xaec30150, 0x8ec20150, 0x8fa9004c, 0x8fa80048, 
+0x10800025, 0x0, 0x8f420218, 0x30420800, 0x14400021, 0x3c020180, 
+0x8faf003c, 0x1e21024, 0x104000fe, 0x1001821, 0x8ec20174, 0x24420001, 
+0xaec20174, 0x8ec20174, 0x100000f8, 0x1001821, 0x8ec2005c, 0xafa20010, 
+0x8ec20060, 0x3c040001, 0x24842f68, 0xafa20014, 0x8ec6003c, 0x8ec70044, 
+0x3c050006, 0x34a5f002, 0xafa80048, 0xc00290f, 0xafa9004c, 0x8ec202b4, 
+0x2403ffbf, 0x283a024, 0x24420001, 0xaec202b4, 0x8ec202b4, 0x8fa80048, 
+0x100000c2, 0x8fa9004c, 0x8f420218, 0x30420400, 0x54400001, 0x25080004, 
+0x96e20460, 0x48102b, 0x10400003, 0x0, 0x3c0f8000, 0xafaf002c, 
+0x110000d2, 0x3c02ffff, 0x8faf003c, 0x1e21024, 0xafa20044, 0x8ec20068, 
+0x8f430280, 0x24420001, 0x304203ff, 0x106200ad, 0x0, 0x8faf002c, 
+0x11e00014, 0x0, 0x8ec3005c, 0x8ec20060, 0x10620009, 0x26cb0060, 
+0x8ec60060, 0x8ec30060, 0x21140, 0x24424dc0, 0x2e28821, 0x24630001, 
+0x10000014, 0x306a00ff, 0x92c20064, 0x1440ffc4, 0x0, 0x8ec202c8, 
+0x24420001, 0xaec202c8, 0x8ec202c8, 0x8ec3003c, 0x8ec20044, 0x1062ffbc, 
+0x26cb0044, 0x8ec60044, 0xafa0002c, 0x8ec30044, 0x21140, 0x24420dc0, 
+0x2e28821, 0x24630001, 0x306a01ff, 0x96e20462, 0x30420010, 0x10400017, 
+0x0, 0x96a2000c, 0x340f8100, 0x144f0013, 0x0, 0x92c200ed, 
+0x14400010, 0x0, 0x96a2000e, 0xa6220016, 0x8ea20008, 0x8ea30004, 
+0x8ea40000, 0x2508fffc, 0xaea2000c, 0xaea30008, 0xaea40004, 0x9622000e, 
+0x25290004, 0x240f0001, 0xa3af0037, 0x34420200, 0xa622000e, 0x9623000a, 
+0x68102b, 0x14400002, 0x3073fff8, 0x1009821, 0x92c200ed, 0x14400012, 
+0x260f021, 0x9523000c, 0x24020800, 0x5462000f, 0xae290018, 0x91220017, 
+0x38430006, 0x2c630001, 0x38420011, 0x2c420001, 0x621825, 0x50600007, 
+0xae290018, 0x95220010, 0x2443000e, 0x73102b, 0x54400001, 0x60f021, 
+0xae290018, 0x92c300ed, 0x8e240000, 0x8e250004, 0x8faf002c, 0x2402000b, 
+0xafa20010, 0x3182b, 0x31ec0, 0xcf1025, 0x431025, 0xafa20014, 
+0x8ec20004, 0xafa20018, 0x8ec200a8, 0x3c03821, 0x1203021, 0xafa80048, 
+0xafa9004c, 0xafaa0050, 0x40f809, 0xafab0054, 0x8fa80048, 0x8fa9004c, 
+0x8faa0050, 0x8fab0054, 0x1440001d, 0x3c050006, 0x3c040001, 0x24842f80, 
+0x8e220018, 0x34a5f009, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 
+0x3c03821, 0xafa80048, 0xafa9004c, 0xc00290f, 0xafa30014, 0x93a20037, 
+0x8fa80048, 0x8fa9004c, 0x1040002a, 0x340f8100, 0x8ea20004, 0x8ea30008, 
+0x8ea4000c, 0xa6af000c, 0xaea20000, 0xaea30004, 0xaea40008, 0x96220016, 
+0x10000020, 0xa6a2000e, 0x8faf0044, 0x11e00007, 0x0, 0x8faf003c, 
+0x9623000e, 0xf1402, 0x34630400, 0xa6220014, 0xa623000e, 0x56680008, 
+0x1334821, 0x9622000e, 0xa628000a, 0x4021, 0x34420004, 0xa622000e, 
+0x1000000c, 0xa2c000ed, 0x3c03001f, 0x3463ffff, 0x24020001, 0x69182b, 
+0xa633000a, 0x10600003, 0xa2c200ed, 0x8ec20540, 0x1224823, 0x1134023, 
+0xafa0002c, 0x1500ff4f, 0xad6a0000, 0x1100001b, 0x0, 0xaec800f0, 
+0xaec900f4, 0xaed500f8, 0x93a20037, 0x10400004, 0x0, 0x8ec200f8, 
+0x24420004, 0xaec200f8, 0x8faf003c, 0x8ec20068, 0xaecf00fc, 0x8f430280, 
+0x24420001, 0x14620006, 0x0, 0x8ec202b8, 0x24420001, 0xaec202b8, 
+0x10000016, 0x8ec202b8, 0x8ec202b0, 0x24420001, 0xaec202b0, 0x10000011, 
+0x8ec202b0, 0x8faf003c, 0x31e4ffff, 0x2484fffc, 0x801821, 0x8ec401b8, 
+0x8ec501bc, 0x3c060001, 0x8cc63510, 0x1021, 0xa32821, 0xa3382b, 
+0x822021, 0x872021, 0xaec401b8, 0xc0f809, 0xaec501bc, 0x8fbf0068, 
+0x8fbe0064, 0x8fb50060, 0x8fb3005c, 0x8fb10058, 0x3e00008, 0x27bd0070, 
+0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 0xafb10020, 0x8ec30040, 
+0x8ec20038, 0x1062004d, 0x0, 0x8ec30038, 0x8ec20040, 0x623823, 
+0x4e20001, 0x24e70200, 0x8ec30044, 0x8ec20040, 0x43102b, 0x14400004, 
+0x24020200, 0x8ec30040, 0x10000005, 0x431823, 0x8ec20044, 0x8ec30040, 
+0x431023, 0x2443ffff, 0xe08821, 0x71102a, 0x54400001, 0x608821, 
+0x8ec90040, 0x8ee40458, 0x8ee5045c, 0x8ec60040, 0x113940, 0x24080002, 
+0xafa80010, 0x8ec80040, 0x94940, 0x1201821, 0x1021, 0xafa80014, 
+0x8ec80010, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x63140, 
+0xafa80018, 0x8ec200a4, 0x24c60dc0, 0x40f809, 0x2e63021, 0x1440000e, 
+0x24030040, 0x8ec20040, 0xafa20010, 0x8ec20044, 0x3c040001, 0x24842f98, 
+0xafa20014, 0x8ec60038, 0x8ec7003c, 0x3c050007, 0xc00290f, 0x34a5f001, 
+0x10000010, 0x0, 0x8ec20030, 0x24420001, 0x50430003, 0x1021, 
+0x8ec20030, 0x24420001, 0xaec20030, 0x8ec20030, 0x21080, 0x571021, 
+0xac510cc0, 0x8ec20040, 0x511021, 0x304201ff, 0xaec20040, 0x8ec30040, 
+0x8ec20038, 0x14620017, 0x0, 0x8ec20000, 0x10400007, 0x2403fdff, 
+0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 
+0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 
+0xaf820060, 0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 
+0xaf800048, 0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 
+0x0, 0x27bdffd8, 0xafbf0024, 0xafb10020, 0x8ec30058, 0x8ec20054, 
+0x1062004d, 0x0, 0x8ec30054, 0x8ec20058, 0x623823, 0x4e20001, 
+0x24e70100, 0x8ec30060, 0x8ec20058, 0x43102b, 0x14400004, 0x24020100, 
+0x8ec30058, 0x10000005, 0x431823, 0x8ec20060, 0x8ec30058, 0x431023, 
+0x2443ffff, 0xe08821, 0x71102a, 0x54400001, 0x608821, 0x8ec90058, 
+0x8ee40468, 0x8ee5046c, 0x8ec60058, 0x113940, 0x24080003, 0xafa80010, 
+0x8ec80058, 0x94940, 0x1201821, 0x1021, 0xafa80014, 0x8ec80010, 
+0xa32821, 0xa3482b, 0x822021, 0x892021, 0x63140, 0xafa80018, 
+0x8ec200a4, 0x24c64dc0, 0x40f809, 0x2e63021, 0x1440000e, 0x24030040, 
+0x8ec20058, 0xafa20010, 0x8ec20060, 0x3c040001, 0x24842fa4, 0xafa20014, 
+0x8ec60054, 0x8ec7005c, 0x3c050007, 0xc00290f, 0x34a5f010, 0x10000010, 
+0x0, 0x8ec20030, 0x24420001, 0x50430003, 0x1021, 0x8ec20030, 
+0x24420001, 0xaec20030, 0x8ec20030, 0x21080, 0x571021, 0xac510cc0, 
+0x8ec20058, 0x511021, 0x304200ff, 0xaec20058, 0x8ec30058, 0x8ec20054, 
+0x14620017, 0x0, 0x8ec20000, 0x10400007, 0x2403feff, 0xaf80004c, 
+0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, 
+0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x431024, 0xaf820060, 
+0x8ec20000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 
+0x8fbf0024, 0x8fb10020, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 
+0x8f820120, 0x8ec300e8, 0x8f820124, 0x8f860128, 0x24020040, 0x24630001, 
+0x50620003, 0x1021, 0x8ec200e8, 0x24420001, 0xaec200e8, 0x8ec200e8, 
+0x8ec400e8, 0x8ec300e4, 0x210c0, 0x24426fc0, 0x14830007, 0x2e22821, 
+0x8f820128, 0x24420020, 0xaf820128, 0x8f820128, 0x10000011, 0xaca00000, 
+0x8ec200e8, 0x24030040, 0x24420001, 0x50430003, 0x1021, 0x8ec200e8, 
+0x24420001, 0x220c0, 0x2e41021, 0x8c426fc4, 0x8f830128, 0x21140, 
+0x621821, 0x2e41021, 0xaf830128, 0xac406fc0, 0x8cc20018, 0x2443fffe, 
+0x2c620018, 0x1040000a, 0x31080, 0x3c010001, 0x220821, 0x8c222fb0, 
+0x400008, 0x0, 0x24020001, 0x3c010001, 0x370821, 0xac2281e8, 
+0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffa8, 0xafbf0050, 
+0xafbe004c, 0xafb50048, 0xafb30044, 0xafb10040, 0x8f830128, 0x8f820124, 
+0x106201e1, 0x0, 0x8f9e0128, 0x8f820128, 0x24420020, 0xaf820128, 
+0x8fc40018, 0x8f820128, 0x2402000b, 0x1482018f, 0x24020002, 0x8fc3001c, 
+0x97c20016, 0x3064ffff, 0xafc20014, 0x3c028000, 0x621024, 0xafc4001c, 
+0xafa2002c, 0x8fab002c, 0x3c020800, 0x11600004, 0x622824, 0x41140, 
+0x10000003, 0x24424dc0, 0x41140, 0x24420dc0, 0x2e2a821, 0x96a2000e, 
+0x3043fffc, 0x30420400, 0x10400003, 0xa6a3000e, 0x10000137, 0x8821, 
+0x10a00004, 0x8821, 0x97d10016, 0x10000132, 0x0, 0x8eab0018, 
+0xafab0034, 0x9563000c, 0x96eb0462, 0x24020800, 0x1462012b, 0xafab003c, 
+0x8fab0034, 0x2573000e, 0x8fab003c, 0x31620002, 0x1040003f, 0x3c030020, 
+0x8ec70540, 0x263102b, 0x14400002, 0x2604821, 0x2674823, 0x25220014, 
+0x43102b, 0x10400027, 0x24030005, 0x91220000, 0x3042000f, 0x14430024, 
+0x1202021, 0x952a0000, 0x25290002, 0x95280000, 0x25290002, 0x95270000, 
+0x25290002, 0x95260000, 0x25290002, 0x95250000, 0x25290002, 0x95230000, 
+0x25290002, 0x95220000, 0x25290002, 0x95240000, 0x25290002, 0x1485021, 
+0x1475021, 0x1465021, 0x1455021, 0x1435021, 0x1425021, 0x95220000, 
+0x95230002, 0x1445021, 0x1425021, 0x1435021, 0xa1c02, 0x3142ffff, 
+0x625021, 0xa1c02, 0x3142ffff, 0x10000009, 0x625021, 0x1202021, 
+0x90850000, 0x3c060020, 0x8ec200ac, 0x30a5000f, 0x40f809, 0x52840, 
+0x304affff, 0x3143ffff, 0x50600001, 0x3403ffff, 0x96a2000e, 0x34420002, 
+0x10000002, 0xa6a2000e, 0x1821, 0xa6a30010, 0x8fab003c, 0x31620001, 
+0x104000e1, 0x0, 0x92620009, 0x38430006, 0x2c630001, 0x38420011, 
+0x2c420001, 0x621825, 0x106000d9, 0x3c030020, 0x8fa60034, 0x8ec70540, 
+0xc3102b, 0x50400001, 0xc73023, 0x24c2000e, 0x43102b, 0x1040001a, 
+0xc02021, 0x94c70000, 0x24c60002, 0x94c50000, 0x24c60002, 0x94c30000, 
+0x24c60002, 0x94c20000, 0x24c60002, 0x94c40000, 0x24c60002, 0xe53821, 
+0xe33821, 0xe23821, 0x94c20000, 0x94c30002, 0xe43821, 0xe23821, 
+0xe33821, 0x71c02, 0x30e2ffff, 0x623821, 0x71c02, 0x30e2ffff, 
+0x10000006, 0x623821, 0x8ec200ac, 0x24050007, 0x40f809, 0x3c060020, 
+0x3047ffff, 0x8fab003c, 0x31620008, 0x10400003, 0x30e8ffff, 0x1000005b, 
+0x4821, 0x96620006, 0x30421fff, 0x10400007, 0x2602821, 0x92620000, 
+0x96630002, 0x3042000f, 0x21080, 0x10000051, 0x624823, 0x3c070020, 
+0x8ec30540, 0xa7102b, 0x50400001, 0xa32823, 0x24a20014, 0x47102b, 
+0x10400015, 0xa02021, 0x90a20000, 0x94a30002, 0x3042000f, 0x21080, 
+0x623023, 0xafa20020, 0x90a30009, 0x24a5000c, 0x94a20000, 0x24a50002, 
+0x94a40000, 0x24a50002, 0xc33021, 0xc23021, 0x94a20000, 0x94a30002, 
+0xc43021, 0xc23021, 0x1000002d, 0xc33021, 0x24a50002, 0xa7102b, 
+0x50400001, 0xa32823, 0x94a60000, 0x802821, 0xa7102b, 0x50400001, 
+0xa32823, 0x90a20000, 0x24850009, 0x3042000f, 0x21080, 0xc23023, 
+0xafa20020, 0xa7102b, 0x50400001, 0xa32823, 0x90a20000, 0x2485000c, 
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002, 
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002, 
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0x24a50002, 
+0xc23021, 0xa7102b, 0x50400001, 0xa32823, 0x94a20000, 0xc23021, 
+0x61c02, 0x30c2ffff, 0x623021, 0x61402, 0x30c3ffff, 0x431021, 
+0x3049ffff, 0x96a2000e, 0x30420004, 0x10400041, 0x0, 0x8f420218, 
+0x30420400, 0x1040003d, 0x3c070020, 0x97c2000e, 0x8fc30008, 0x8ec60540, 
+0x621821, 0x2463fffc, 0x67102b, 0x50400001, 0x661823, 0x602821, 
+0x24a20004, 0x47102b, 0x5040000a, 0xa7102b, 0x90a20000, 0x90a40001, 
+0x90a30002, 0x21200, 0x441021, 0x90a40003, 0x31a00, 0x10000017, 
+0x431021, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x22200, 
+0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x822021, 
+0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x24a50001, 0x21200, 
+0x822021, 0xa7102b, 0x50400001, 0xa62823, 0x90a20000, 0x822021, 
+0x41c02, 0x3082ffff, 0x622021, 0x41402, 0x3083ffff, 0x431021, 
+0x3042ffff, 0x1024021, 0x81c02, 0x3102ffff, 0x624021, 0x81c02, 
+0x3102ffff, 0x624021, 0x3108ffff, 0x8fc20014, 0x488823, 0x111402, 
+0x2228821, 0x2298821, 0x111402, 0x2228821, 0x3231ffff, 0x52200001, 
+0x3411ffff, 0x96a2000e, 0x34420001, 0xa6a2000e, 0x96a2000e, 0x24080002, 
+0x30420004, 0x10400002, 0xa6b10012, 0x24080004, 0x8ec90068, 0x8ee40478, 
+0x8ee5047c, 0xafa80010, 0x8ec80068, 0x8fab002c, 0x2a03021, 0x24070020, 
+0x10b4025, 0xafa80014, 0x8ec80008, 0x94940, 0x1201821, 0xafa80018, 
+0x8ec800a8, 0x1021, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 
+0x892021, 0x1440000e, 0x0, 0x8f820120, 0xafa20010, 0x8f820128, 
+0x3c040001, 0x24843010, 0xafa20014, 0x8fc6001c, 0x8f870124, 0x3c050008, 
+0xc00290f, 0x34a50001, 0x1000005f, 0x0, 0x8ec20068, 0x24420001, 
+0x304203ff, 0xaec20068, 0x8fab002c, 0x11600006, 0x0, 0x8ec202c0, 
+0x2442ffff, 0xaec202c0, 0x10000005, 0x8ec202c0, 0x8ec202bc, 0x2442ffff, 
+0xaec202bc, 0x8ec202bc, 0x8ec202c4, 0x2442ffff, 0xaec202c4, 0x1000004a, 
+0x8ec202c4, 0x14820005, 0x24020004, 0x8ec20048, 0x24420001, 0x10000044, 
+0xaec20048, 0x14820036, 0x38830011, 0x97c2001e, 0xafc2001c, 0x8ec20048, 
+0x24420001, 0xaec20048, 0x8f430240, 0x43102b, 0x14400039, 0x24070008, 
+0x8ed10068, 0x8ee40490, 0x8ee50494, 0x8ec30008, 0x8f860120, 0x24020013, 
+0xafa20010, 0xafb10014, 0xafa30018, 0x8ec200a8, 0x40f809, 0x24c6001c, 
+0x1440000b, 0x24020001, 0x3c040001, 0x24842f0c, 0xafb10010, 0xafa00014, 
+0x8ec60068, 0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f008, 0x1021, 
+0x14400005, 0x24020001, 0x3c010001, 0x370821, 0x1000000a, 0xac2281e0, 
+0x3c010001, 0x370821, 0xac2081e0, 0x8ec20268, 0xaec00048, 0xaed1006c, 
+0x24420001, 0xaec20268, 0x8ec20268, 0x8ec2027c, 0x24420001, 0xaec2027c, 
+0x1000000d, 0x8ec2027c, 0x2c630001, 0x38820013, 0x2c420001, 0x621825, 
+0x14600004, 0x24020001, 0x24020012, 0x14820004, 0x24020001, 0x3c010001, 
+0x370821, 0xac2281e8, 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 
+0x8fb10040, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x0, 
+0x0, 0x0, 0x8ec20538, 0xaf8200c0, 0x8ec20538, 0xaf8200c4, 
+0x8ec20538, 0xaf8200c8, 0x8ec20534, 0xaf8200d0, 0x8ec20534, 0xaf8200d4, 
+0x8ec20534, 0x3e00008, 0xaf8200d8, 0x27bdffe8, 0x27840208, 0x27450200, 
+0xafbf0010, 0xc0029a2, 0x24060008, 0x8f420204, 0xc003c86, 0xaf820210, 
+0x24040001, 0x8f460248, 0x24020004, 0x3c010001, 0xac22340c, 0xc0046cc, 
+0x24050004, 0x3c020001, 0x8c423408, 0x30420001, 0x10400007, 0x24020001, 
+0x3c010001, 0xac22340c, 0x24040001, 0x24050001, 0xc0046cc, 0x3c06601b, 
+0x8ec20548, 0x8ec4054c, 0x8ec30550, 0x3c010001, 0xac203404, 0x3c010001, 
+0xac20341c, 0x21640, 0x42140, 0x34840403, 0x441025, 0x31bc0, 
+0x431025, 0xaf82021c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 
+0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, 
+0x3c040001, 0x248430dc, 0xc00290f, 0x3821, 0x8ec20368, 0x24420001, 
+0xaec20368, 0x8ec20368, 0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, 
+0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 
+0xafb10018, 0x8f910220, 0x8ec202fc, 0x24420001, 0xaec202fc, 0x8ec202fc, 
+0x8ec30310, 0x3c020001, 0x8c42341c, 0x3c040001, 0x248430e8, 0xafa20014, 
+0xafa30010, 0x8ec70314, 0x3c050008, 0xc00290f, 0x2203021, 0x3c024000, 
+0x2221024, 0x104000e5, 0x3c040100, 0x8ec20314, 0x24420001, 0xaec20314, 
+0x8ec20314, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420004, 
+0xaf820220, 0x8f8200e0, 0x8f8300c4, 0x3c02001f, 0x3442ffff, 0x24690008, 
+0x49102b, 0x10400003, 0x0, 0x8ec20540, 0x1224823, 0x8f8700c8, 
+0x8f850120, 0x8f840124, 0x10000005, 0x5821, 0x8ec20534, 0x82102b, 
+0x50400001, 0x27644800, 0x10a40010, 0x316200ff, 0x8c820018, 0x38430007, 
+0x2c630001, 0x3842000b, 0x2c420001, 0x621825, 0x5060fff3, 0x24840020, 
+0x8ec20328, 0x240b0001, 0x24420001, 0xaec20328, 0x8ec20328, 0x8c870008, 
+0x316200ff, 0x14400078, 0x0, 0x92c200ed, 0x14400075, 0x0, 
+0x8f8500e4, 0x8f8200e0, 0x2403fff8, 0x433024, 0xc51023, 0x218c3, 
+0x4620001, 0x24630100, 0x8f8a00c4, 0x10600005, 0x24020001, 0x10620009, 
+0x0, 0x10000021, 0x0, 0x8ec20318, 0x1403821, 0x24420001, 
+0xaec20318, 0x10000060, 0x8ec20318, 0x8ec2031c, 0x24420001, 0xaec2031c, 
+0x8ca70000, 0x8ec20540, 0x8ec3031c, 0x1471823, 0x43102b, 0x10400004, 
+0x2c62233f, 0x8ec20540, 0x621821, 0x2c62233f, 0x14400051, 0x3c020100, 
+0xaca20004, 0x8f8200e8, 0x24420008, 0xaf8200e8, 0x8f8200e8, 0x8f8200e4, 
+0x1403821, 0x24420008, 0xaf8200e4, 0x10000046, 0x8f8200e4, 0x8ec20320, 
+0x24420001, 0xaec20320, 0x8ca80000, 0x8ec20540, 0x8ec30320, 0x1092023, 
 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 
-0x82102b, 0x10400006, 0x316200ff, 0x1440001c, 0x3c02fdff, 0x92c200ed, 
-0x14400019, 0x3c02fdff, 0xaf8700c8, 0x8f8400c8, 0x8f8300c4, 0x8ec20540, 
-0x832023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, 
-0x8ec20544, 0x2c830001, 0x44102b, 0x431025, 0x10400009, 0x3c02fdff, 
-0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0x3c034000, 0x431025, 
-0x10000075, 0xaf820220, 0x3442ffff, 0x8ec30324, 0x282a024, 0x24020001, 
-0xa2c200ec, 0x24630001, 0xaec30324, 0x1000006c, 0x8ec20324, 0x2241024, 
-0x10400013, 0x3c130200, 0x8ec20300, 0x24420001, 0xaec20300, 0x8ec20300, 
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x441025, 0xaf820220, 
-0x3c020004, 0x2221024, 0x14400005, 0x3c130200, 0xc003a65, 0x0, 
-0x10000057, 0x0, 0x2331024, 0x50400008, 0x3c130400, 0x8ec20304, 
-0x24420001, 0xaec20304, 0xc003a65, 0x8ec20304, 0x10000019, 0x0, 
-0x2331024, 0x1040001d, 0x3c020800, 0x8f830224, 0x24021402, 0x14620009, 
-0x3c050008, 0x3c040001, 0x24842f94, 0xafa00010, 0xafa00014, 0x8f860224, 
-0x34a5ffff, 0xc0028eb, 0x3821, 0x8ec20308, 0x24420001, 0xaec20308, 
-0x8ec20308, 0x8f820220, 0x2202021, 0x34420002, 0xc004430, 0xaf820220, 
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x531025, 0x1000002e, 
-0xaf820220, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c, 
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50403, 0xc0028eb, 0x3821, 
-0x3c021000, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c, 
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50401, 0xc0028eb, 0x3821, 
-0x3c022000, 0x2221024, 0x10400009, 0x3c050008, 0x3c040001, 0x24842f7c, 
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50402, 0xc0028eb, 0x3821, 
-0x6210009, 0x3c050008, 0x3c040001, 0x24842f7c, 0xafa00010, 0xafa00014, 
-0x8f860220, 0x34a50404, 0xc0028eb, 0x3821, 0x8fbf0020, 0x8fb3001c, 
-0x8fb10018, 0x3e00008, 0x27bd0028, 0x3e00008, 0x0, 0x3c020001, 
-0x8c4232bc, 0x27bdffc0, 0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 
-0x1040000f, 0xafb10028, 0x3c040001, 0x24842fa0, 0x3c050008, 0xafa00010, 
-0xafa00014, 0x8f860220, 0x34a50498, 0x24020001, 0x3c010001, 0xac2032bc, 
-0x3c010001, 0xac2232b0, 0xc0028eb, 0x3821, 0x3c037fff, 0x8f420268, 
-0x3463ffff, 0x3c04fdff, 0x431024, 0xaf420268, 0x8ee204a8, 0x3484ffff, 
-0x30420002, 0x10400091, 0x284a024, 0x3c040600, 0x8ee204a8, 0x34842000, 
-0x2403fffd, 0x431024, 0xaee204a8, 0xafa40020, 0x8ec3002c, 0x240200ff, 
-0x10620004, 0x27a70020, 0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 
-0x8f420228, 0x1662000f, 0x0, 0x3c040001, 0x24842f58, 0xafa00010, 
-0xafa00014, 0x8ec6002c, 0x8f470228, 0x3c050009, 0xc0028eb, 0x34a5f00f, 
-0x8ec202a0, 0x24420001, 0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 
-0x210c0, 0x571021, 0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 
-0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 
-0xa821, 0x241e000c, 0x8ec8002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 
-0x24070008, 0xafbe0010, 0xafb30014, 0x840c0, 0x1001821, 0x1021, 
-0x8ec80008, 0xa32821, 0xa3482b, 0x822021, 0x892021, 0x630c0, 
-0xafa80018, 0x8ec200a8, 0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 
-0x24150001, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 
-0x32a200ff, 0x54400011, 0xaed3002c, 0x3c040001, 0x24842f64, 0xafa00010, 
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 
-0x8ec2026c, 0x24150001, 0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 
-0x32a200ff, 0x8f830054, 0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 
-0x10400017, 0xa821, 0x3c1e0020, 0x24130011, 0x8ec20008, 0x8ee40488, 
-0x8ee5048c, 0x8ec3002c, 0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 
-0xafa20018, 0x8ec200a8, 0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 
-0x0, 0x8f820054, 0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 
-0x32a200ff, 0x1440000f, 0x0, 0x3c040001, 0x24842f70, 0xafa00010, 
-0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0x34a5f011, 0xc0028eb, 
-0x0, 0x8ec202d0, 0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 
-0x24420001, 0xaec20250, 0x8ec20250, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 
-0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0040, 0x3c020001, 0x8c4232bc, 
-0x27bdffe0, 0x1440000d, 0xafbf0018, 0x3c040001, 0x24842fac, 0x3c050008, 
-0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, 0x24020001, 0x3c010001, 
-0xac2232bc, 0xc0028eb, 0x3821, 0x92c2011d, 0x10400008, 0x24040001, 
-0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 
-0x24040001, 0xc004785, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 
-0x27bd0020, 0x0, 0x86102b, 0x50400001, 0x872023, 0xc41023, 
-0x24843, 0x125102b, 0x1040001b, 0x91040, 0x824021, 0x88102b, 
-0x10400007, 0x1821, 0x94820000, 0x24840002, 0x621821, 0x88102b, 
-0x1440fffb, 0x0, 0x602021, 0xc73023, 0xa91023, 0x21040, 
-0xc22821, 0xc5102b, 0x10400007, 0x1821, 0x94c20000, 0x24c60002, 
-0x621821, 0xc5102b, 0x1440fffb, 0x0, 0x1000000d, 0x832021, 
-0x51040, 0x822821, 0x85102b, 0x10400007, 0x1821, 0x94820000, 
-0x24840002, 0x621821, 0x85102b, 0x1440fffb, 0x0, 0x602021, 
-0x41c02, 0x3082ffff, 0x622021, 0x41c02, 0x3082ffff, 0x622021, 
-0x3e00008, 0x3082ffff, 0x3e00008, 0x0, 0x8f820220, 0x34420002, 
-0xaf820220, 0x3c020001, 0x8c4254b8, 0x30424000, 0x10400054, 0x24040001, 
-0x8f820200, 0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 0x621824, 
-0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 
-0x1444004d, 0x42040, 0xc4102b, 0x1040fff1, 0x0, 0x8f820200, 
-0x451025, 0xaf820200, 0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
-0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1440000f, 
-0x0, 0x8f820220, 0x3c03ffff, 0x34637fff, 0x431024, 0xaf820220, 
+0x44102b, 0x10400003, 0x3c030100, 0x10000034, 0x1003821, 0x8ca20004, 
+0x431025, 0xaca20004, 0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, 
+0x10a60025, 0x3c080100, 0x8ec20174, 0x24420001, 0xaec20174, 0x8ca20004, 
+0x8ec30174, 0x481024, 0x1440000e, 0x0, 0x8ca30000, 0x8ec20540, 
+0x692023, 0x44102b, 0x10400003, 0x0, 0x8ec20540, 0x822021, 
+0x8ec20544, 0x44102b, 0x10400006, 0x0, 0x603821, 0x8ec20544, 
+0x44102b, 0x1440000a, 0x0, 0x8ca20004, 0x481025, 0xaca20004, 
+0x8f8200e4, 0x24450008, 0xaf8500e4, 0x8f8500e4, 0x14a6ffdf, 0x0, 
+0x14a60005, 0x0, 0x1403821, 0xaf8600e4, 0x10000003, 0xaf8600e8, 
+0xaf8500e4, 0xaf8500e8, 0x8f8300c8, 0x8ec20540, 0x692023, 0x44102b, 
+0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x82102b, 
+0x50400008, 0x5821, 0x8ec20540, 0xe92023, 0x44102b, 0x10400003, 
+0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x82102b, 0x10400006, 
+0x316200ff, 0x1440001c, 0x3c02fdff, 0x92c200ed, 0x14400019, 0x3c02fdff, 
+0xaf8700c8, 0x8f8400c8, 0x8f8300c4, 0x8ec20540, 0x832023, 0x44102b, 
+0x10400003, 0x0, 0x8ec20540, 0x822021, 0x8ec20544, 0x2c830001, 
+0x44102b, 0x431025, 0x10400009, 0x3c02fdff, 0x8f820220, 0x3c0308ff, 
+0x3463fffb, 0x431024, 0x3c034000, 0x431025, 0x10000075, 0xaf820220, 
+0x3442ffff, 0x8ec30324, 0x282a024, 0x24020001, 0xa2c200ec, 0x24630001, 
+0xaec30324, 0x1000006c, 0x8ec20324, 0x2241024, 0x10400013, 0x3c130200, 
+0x8ec20300, 0x24420001, 0xaec20300, 0x8ec20300, 0x8f820220, 0x3c0308ff, 
+0x3463ffff, 0x431024, 0x441025, 0xaf820220, 0x3c020004, 0x2221024, 
+0x14400005, 0x3c130200, 0xc003ab1, 0x0, 0x10000057, 0x0, 
+0x2331024, 0x50400008, 0x3c130400, 0x8ec20304, 0x24420001, 0xaec20304, 
+0xc003ab1, 0x8ec20304, 0x10000019, 0x0, 0x2331024, 0x1040001d, 
+0x3c020800, 0x8f830224, 0x24021402, 0x14620009, 0x3c050008, 0x3c040001, 
+0x248430f4, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc00290f, 
+0x3821, 0x8ec20308, 0x24420001, 0xaec20308, 0x8ec20308, 0x8f820220, 
+0x2202021, 0x34420002, 0xc00447c, 0xaf820220, 0x8f820220, 0x3c0308ff, 
+0x3463ffff, 0x431024, 0x531025, 0x1000002e, 0xaf820220, 0x2221024, 
+0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, 
+0x8f860220, 0x34a50403, 0xc00290f, 0x3821, 0x3c021000, 0x2221024, 
+0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, 
+0x8f860220, 0x34a50401, 0xc00290f, 0x3821, 0x3c022000, 0x2221024, 
+0x10400009, 0x3c050008, 0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, 
+0x8f860220, 0x34a50402, 0xc00290f, 0x3821, 0x6210009, 0x3c050008, 
+0x3c040001, 0x248430dc, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50404, 
+0xc00290f, 0x3821, 0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, 
+0x27bd0028, 0x3e00008, 0x0, 0x3c020001, 0x8c42341c, 0x27bdffc0, 
+0xafbf0038, 0xafbe0034, 0xafb50030, 0xafb3002c, 0x1040000f, 0xafb10028, 
+0x3c040001, 0x24843100, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 
+0x34a50498, 0x24020001, 0x3c010001, 0xac20341c, 0x3c010001, 0xac223410, 
+0xc00290f, 0x3821, 0x3c037fff, 0x8f420268, 0x3463ffff, 0x3c04fdff, 
+0x431024, 0xaf420268, 0x8ee204a8, 0x3484ffff, 0x30420002, 0x10400091, 
+0x284a024, 0x3c040600, 0x8ee204a8, 0x34842000, 0x2403fffd, 0x431024, 
+0xaee204a8, 0xafa40020, 0x8ec3002c, 0x240200ff, 0x10620004, 0x27a70020, 
+0x8ec2002c, 0x10000002, 0x24530001, 0x9821, 0x8f420228, 0x1662000f, 
+0x0, 0x3c040001, 0x248430b8, 0xafa00010, 0xafa00014, 0x8ec6002c, 
+0x8f470228, 0x3c050009, 0xc00290f, 0x34a5f00f, 0x8ec202a0, 0x24420001, 
+0xaec202a0, 0x1000006d, 0x8ec202a0, 0x8ec2002c, 0x210c0, 0x571021, 
+0x8ce30000, 0x8ce40004, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 
+0x247103e8, 0x2221023, 0x2c4203e9, 0x1040001e, 0xa821, 0x241e000c, 
+0x8ec8002c, 0x8ee40428, 0x8ee5042c, 0x8ec6002c, 0x24070008, 0xafbe0010, 
+0xafb30014, 0x840c0, 0x1001821, 0x1021, 0x8ec80008, 0xa32821, 
+0xa3482b, 0x822021, 0x892021, 0x630c0, 0xafa80018, 0x8ec200a8, 
+0x24c604c0, 0x40f809, 0x2e63021, 0x54400006, 0x24150001, 0x8f820054, 
+0x2221023, 0x2c4203e9, 0x1440ffe5, 0x0, 0x32a200ff, 0x54400011, 
+0xaed3002c, 0x3c040001, 0x248430c4, 0xafa00010, 0xafa00014, 0x8f860120, 
+0x8f870124, 0x3c050009, 0x10000030, 0x34a5f010, 0x8ec2026c, 0x24150001, 
+0x24420001, 0xaec2026c, 0x8ec2026c, 0x1000001f, 0x32a200ff, 0x8f830054, 
+0x8f820054, 0x247103e8, 0x2221023, 0x2c4203e9, 0x10400017, 0xa821, 
+0x3c1e0020, 0x24130011, 0x8ec20008, 0x8ee40488, 0x8ee5048c, 0x8ec3002c, 
+0x8f860120, 0xafb30010, 0x5e1025, 0xafa30014, 0xafa20018, 0x8ec200a8, 
+0x24070008, 0x40f809, 0x24c6001c, 0x1440ffe2, 0x0, 0x8f820054, 
+0x2221023, 0x2c4203e9, 0x1440ffed, 0x0, 0x32a200ff, 0x1440000f, 
+0x0, 0x3c040001, 0x248430d0, 0xafa00010, 0xafa00014, 0x8f860120, 
+0x8f870124, 0x3c050009, 0x34a5f011, 0xc00290f, 0x0, 0x8ec202d0, 
+0x24420001, 0xaec202d0, 0x8ec202d0, 0x8ec20250, 0x24420001, 0xaec20250, 
+0x8ec20250, 0x8fbf0038, 0x8fbe0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 
+0x3e00008, 0x27bd0040, 0x3c020001, 0x8c42341c, 0x27bdffe0, 0x1440000d, 
+0xafbf0018, 0x3c040001, 0x2484310c, 0x3c050008, 0xafa00010, 0xafa00014, 
+0x8f860220, 0x34a50499, 0x24020001, 0x3c010001, 0xac22341c, 0xc00290f, 
+0x3821, 0x92c2011d, 0x10400008, 0x24040001, 0x8f820220, 0x3c0308ff, 
+0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x24040001, 0xc0047d1, 
+0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x86102b, 0x50400001, 0x872023, 0xc41023, 0x24843, 0x125102b, 
+0x1040001b, 0x91040, 0x824021, 0x88102b, 0x10400007, 0x1821, 
+0x94820000, 0x24840002, 0x621821, 0x88102b, 0x1440fffb, 0x0, 
+0x602021, 0xc73023, 0xa91023, 0x21040, 0xc22821, 0xc5102b, 
+0x10400007, 0x1821, 0x94c20000, 0x24c60002, 0x621821, 0xc5102b, 
+0x1440fffb, 0x0, 0x1000000d, 0x832021, 0x51040, 0x822821, 
+0x85102b, 0x10400007, 0x1821, 0x94820000, 0x24840002, 0x621821, 
+0x85102b, 0x1440fffb, 0x0, 0x602021, 0x41c02, 0x3082ffff, 
+0x622021, 0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 0x3082ffff, 
+0x3e00008, 0x0, 0x8f820220, 0x34420002, 0xaf820220, 0x3c020001, 
+0x8c425618, 0x30424000, 0x10400054, 0x24040001, 0x8f820200, 0x24067fff, 
+0x8f830200, 0x30450002, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 
 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 
-0x1440000d, 0x0, 0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 
-0x1440fffc, 0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1040001b, 
-0x1021, 0x8f830220, 0x24020001, 0x10000015, 0x3c04f700, 0x8f820220, 
-0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, 0x2403fffd, 0x431024, 
-0xaf820220, 0x8f820220, 0x3c030300, 0x431024, 0x14400003, 0x0, 
-0x10000008, 0x1021, 0x8f820220, 0x34420002, 0xaf820220, 0x8f830220, 
-0x24020001, 0x641825, 0xaf830220, 0x3e00008, 0x0, 0x2021, 
-0x3c050100, 0x24020001, 0xaf80021c, 0xaf820200, 0xaf820220, 0x27625000, 
-0xaf8200c0, 0x27625000, 0xaf8200c4, 0x27625000, 0xaf8200c8, 0x27625000, 
-0xaf8200d0, 0x27625000, 0xaf8200d4, 0x27625000, 0xaf8200d8, 0x27623000, 
-0xaf8200e0, 0x27623000, 0xaf8200e4, 0x27623000, 0xaf8200e8, 0x27622800, 
-0xaf8200f0, 0x27622800, 0xaf8200f4, 0x27622800, 0xaf8200f8, 0x418c0, 
-0x24840001, 0x3631021, 0xac453004, 0x3631021, 0xac403000, 0x28820200, 
-0x1440fff9, 0x418c0, 0x2021, 0x418c0, 0x24840001, 0x3631021, 
-0xac402804, 0x3631021, 0xac402800, 0x28820100, 0x1440fff9, 0x418c0, 
-0xaf80023c, 0x24030080, 0x24040100, 0xac600000, 0x24630004, 0x64102b, 
-0x5440fffd, 0xac600000, 0x8f830040, 0x3c02f000, 0x621824, 0x3c025000, 
-0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 
-0x24020800, 0x10000008, 0x0, 0x10620004, 0x24020800, 0x10000004, 
-0x0, 0x24020700, 0x3c010001, 0xac2232c0, 0x3e00008, 0x0, 
-0x27bdffc8, 0xafbf0034, 0xafb50030, 0xafb3002c, 0xafb10028, 0x3c010001, 
-0xc00440d, 0xac2032a8, 0x24040001, 0x2821, 0x27a60020, 0x34028000, 
-0xc00402a, 0xa7a20020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 
-0xc003fe8, 0x27a60020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 
-0xc003fe8, 0x27a60020, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 
-0xc003fe8, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 
-0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 
-0xc003fe8, 0x27a6001a, 0x97a20020, 0x10400024, 0x24020001, 0x3c020001, 
-0x8c4232a8, 0x97a30018, 0x34420001, 0x3c010001, 0xac2232a8, 0x24020015, 
-0x14620004, 0x3402f423, 0x97a3001a, 0x10620018, 0x24020003, 0x97a30018, 
-0x24027810, 0x14620014, 0x24020002, 0x97a3001a, 0x24020001, 0x14620010, 
-0x24020002, 0x1000000e, 0x24020004, 0x3c020001, 0x8c4232a8, 0x34420008, 
-0x3c010001, 0xac2232a8, 0x10000058, 0x24020004, 0x3c020001, 0x8c4232a8, 
-0x34420004, 0x3c010001, 0x100000a8, 0xac2232a8, 0x3c010001, 0xac2233dc, 
-0x24020e00, 0xaf820238, 0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, 
-0xac2332ac, 0x10000002, 0x248401f4, 0x8f820054, 0x821023, 0x2c4201f5, 
-0x1440fffc, 0x3c0200c8, 0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x1444004d, 0x42040, 
+0xc4102b, 0x1040fff1, 0x0, 0x8f820200, 0x451025, 0xaf820200, 
+0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 
+0x8f820220, 0x3c030004, 0x431024, 0x1440000f, 0x0, 0x8f820220, 
+0x3c03ffff, 0x34637fff, 0x431024, 0xaf820220, 0x8f830054, 0x8f820054, 
+0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
+0x0, 0x8f820220, 0x3c030004, 0x431024, 0x1440000d, 0x0, 
+0x8f820220, 0x34428000, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 
+0x8f820220, 0x3c030004, 0x431024, 0x1040001b, 0x1021, 0x8f830220, 
+0x24020001, 0x10000015, 0x3c04f700, 0x8f820220, 0x3c04f700, 0x441025, 
+0xaf820220, 0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, 0x8f820220, 
+0x3c030300, 0x431024, 0x14400003, 0x0, 0x10000008, 0x1021, 
+0x8f820220, 0x34420002, 0xaf820220, 0x8f830220, 0x24020001, 0x641825, 
+0xaf830220, 0x3e00008, 0x0, 0x2021, 0x3c050100, 0x24020001, 
+0xaf80021c, 0xaf820200, 0xaf820220, 0x27625000, 0xaf8200c0, 0x27625000, 
+0xaf8200c4, 0x27625000, 0xaf8200c8, 0x27625000, 0xaf8200d0, 0x27625000, 
+0xaf8200d4, 0x27625000, 0xaf8200d8, 0x27623000, 0xaf8200e0, 0x27623000, 
+0xaf8200e4, 0x27623000, 0xaf8200e8, 0x27622800, 0xaf8200f0, 0x27622800, 
+0xaf8200f4, 0x27622800, 0xaf8200f8, 0x418c0, 0x24840001, 0x3631021, 
+0xac453004, 0x3631021, 0xac403000, 0x28820200, 0x1440fff9, 0x418c0, 
+0x2021, 0x418c0, 0x24840001, 0x3631021, 0xac402804, 0x3631021, 
+0xac402800, 0x28820100, 0x1440fff9, 0x418c0, 0xaf80023c, 0x24030080, 
+0x24040100, 0xac600000, 0x24630004, 0x64102b, 0x5440fffd, 0xac600000, 
+0x8f830040, 0x3c02f000, 0x621824, 0x3c025000, 0x1062000c, 0x43102b, 
+0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x10000008, 
+0x0, 0x10620004, 0x24020800, 0x10000004, 0x0, 0x24020700, 
+0x3c010001, 0xac223420, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0034, 
+0xafb50030, 0xafb3002c, 0xafb10028, 0x3c010001, 0xc004459, 0xac203408, 
+0x24040001, 0x2821, 0x27a60020, 0x34028000, 0xc004076, 0xa7a20020, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004034, 0x27a60020, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050001, 0xc004034, 0x27a60020, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050002, 0xc004034, 0x27a60018, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 
+0x2c420065, 0x1440fffc, 0x24040001, 0x24050003, 0xc004034, 0x27a6001a, 
+0x97a20020, 0x10400024, 0x24020001, 0x3c020001, 0x8c423408, 0x97a30018, 
+0x34420001, 0x3c010001, 0xac223408, 0x24020015, 0x14620004, 0x3402f423, 
+0x97a3001a, 0x10620018, 0x24020003, 0x97a30018, 0x24027810, 0x14620014, 
+0x24020002, 0x97a3001a, 0x24020001, 0x14620010, 0x24020002, 0x1000000e, 
+0x24020004, 0x3c020001, 0x8c423408, 0x34420008, 0x3c010001, 0xac223408, 
+0x10000058, 0x24020004, 0x3c020001, 0x8c423408, 0x34420004, 0x3c010001, 
+0x100000a8, 0xac223408, 0x3c010001, 0xac22353c, 0x24020e00, 0xaf820238, 
+0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, 0xac23340c, 0x10000002, 
+0x248401f4, 0x8f820054, 0x821023, 0x2c4201f5, 0x1440fffc, 0x3c0200c8, 
+0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, 0x246301f4, 
+0x8f820054, 0x621023, 0x2c4201f5, 0x1440fffc, 0x8821, 0x3c1300c8, 
+0x367301f6, 0x2415fffd, 0xc003f77, 0x0, 0x8f830054, 0x8f820054, 
 0x10000002, 0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, 0x1440fffc, 
-0x8821, 0x3c1300c8, 0x367301f6, 0x2415fffd, 0xc003f2b, 0x0, 
-0x8f830054, 0x8f820054, 0x10000002, 0x246301f4, 0x8f820054, 0x621023, 
-0x2c4201f5, 0x1440fffc, 0x0, 0xaf930238, 0x8f830054, 0x8f820054, 
-0x10000002, 0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 
-0x0, 0x8f820220, 0x34420002, 0xaf820220, 0x8f820200, 0x24040001, 
-0x24057fff, 0x551024, 0xaf820200, 0xaf840204, 0x8f830054, 0x8f820054, 
+0x0, 0xaf930238, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, 
+0x34420002, 0xaf820220, 0x8f820200, 0x24040001, 0x24057fff, 0x551024, 
+0xaf820200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 
+0x14440005, 0x34028000, 0x42040, 0xa4102b, 0x1040fff0, 0x34028000, 
+0x1082ffa6, 0x26310001, 0x2e220014, 0x1440ffce, 0x24020004, 0x3c010001, 
+0xac22340c, 0x8821, 0x3c13ffff, 0x36733f7f, 0xc003f77, 0x0, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x531024, 0x34425080, 
+0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 0x8f820054, 
+0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820044, 0x531024, 
+0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, 
+0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 0x8f820054, 0x10000002, 
+0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x0, 
+0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 0x8f830200, 0x24057fff, 
+0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 
 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
 0x0, 0x8f820224, 0x14440005, 0x34028000, 0x42040, 0xa4102b, 
-0x1040fff0, 0x34028000, 0x1082ffa6, 0x26310001, 0x2e220014, 0x1440ffce, 
-0x24020004, 0x3c010001, 0xac2232ac, 0x8821, 0x3c13ffff, 0x36733f7f, 
-0xc003f2b, 0x0, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
-0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 
-0x531024, 0x34425080, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 
-0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 
-0x8f820044, 0x531024, 0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, 
-0x10000002, 0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 
-0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, 
-0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 
-0x1440fffc, 0x0, 0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 
-0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x14440005, 0x34028000, 
-0x42040, 0xa4102b, 0x1040fff0, 0x34028000, 0x1082ff57, 0x26310001, 
-0x2e220064, 0x1440ffb0, 0x0, 0x3c020001, 0x8c4232a8, 0x30420004, 
-0x14400007, 0x3c08fff0, 0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 
-0xaf820044, 0x3c08fff0, 0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, 
-0x8ce733dc, 0x3c040001, 0x24843080, 0x24020001, 0x3c010001, 0xac2232b0, 
-0xafa60010, 0x3c060001, 0x8cc632a8, 0x97a2001a, 0x3c05000d, 0x34a50100, 
-0x3c010001, 0xac2032ac, 0x681821, 0x3c010001, 0xac2333d4, 0xc0028eb, 
-0xafa20014, 0x8fbf0034, 0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 
-0x27bd0038, 0x27bdffe8, 0x24070004, 0x3c040001, 0x8c8432ac, 0x3021, 
-0x24020001, 0x1482000a, 0xafbf0010, 0x3c020001, 0x8c4254bc, 0x3c050004, 
-0x30428000, 0x1040000c, 0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240, 
-0x3c020001, 0x8c4254bc, 0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 
-0x3c05001e, 0x34a58480, 0x3c020001, 0x8c4233d4, 0x8f830054, 0x451021, 
-0x431023, 0x45102b, 0x1440002e, 0x0, 0x3c020001, 0x8c4232b4, 
-0x1440002a, 0x2cc20001, 0x7182b, 0x431024, 0x1040001d, 0x0, 
-0x3c090001, 0x8d2932a8, 0x240b0001, 0x3c054000, 0x3c080001, 0x250854bc, 
-0x250afffc, 0x42042, 0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 
-0x5040000b, 0x2cc20001, 0x148b0004, 0x0, 0x8d020000, 0x10000003, 
-0x451024, 0x8d420000, 0x451024, 0x54400001, 0x24060001, 0x2cc20001, 
-0x7182b, 0x431024, 0x5440ffed, 0x42042, 0x3c010001, 0x10c00020, 
-0xac2432ac, 0x8f830054, 0x24020001, 0x3c010001, 0xac2232b0, 0x3c010001, 
-0xac2333d4, 0x3c020001, 0x8c4232b0, 0x10400004, 0x24020001, 0x3c010001, 
-0xac2032b0, 0xaee279c8, 0x8ee379c8, 0x24020008, 0x10620005, 0x24020001, 
-0xc003dd7, 0x0, 0x1000000b, 0x0, 0x3c030001, 0x8c6332ac, 
-0x10620007, 0x2402000e, 0x3c030001, 0x8c635430, 0x10620003, 0x0, 
-0xc004430, 0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 
-0x3c03fdff, 0x3c040001, 0x8c8432ac, 0x3c020001, 0x8c4232c4, 0x3463ffff, 
-0x283a024, 0x14820006, 0xafbf0018, 0x8ee379c8, 0x3c020001, 0x8c4232c8, 
-0x10620006, 0x0, 0x8ee279c8, 0x3c010001, 0xac2432c4, 0x3c010001, 
-0xac2232c8, 0x3c030001, 0x8c6332ac, 0x24020002, 0x10620139, 0x2c620003, 
-0x10400005, 0x24020001, 0x1062000a, 0x0, 0x10000131, 0x0, 
-0x24020004, 0x10620070, 0x24020008, 0x106200ac, 0x24020001, 0x1000012a, 
-0x0, 0x8ee279c8, 0x2443ffff, 0x2c620008, 0x10400127, 0x31080, 
-0x3c010001, 0x220821, 0x8c223098, 0x400008, 0x0, 0xc003f2b, 
-0x0, 0x3c020001, 0x8c4232b8, 0x3c010001, 0xac203240, 0x104000e8, 
-0x24020002, 0xaee279c8, 0x3c010001, 0x10000116, 0xac2032b8, 0xc00406b, 
-0x0, 0x3c030001, 0x8c6332d0, 0x24020011, 0x1462010f, 0x24020003, 
-0x100000aa, 0x0, 0x3c050001, 0x8ca532ac, 0x3c060001, 0x8cc654bc, 
-0xc004680, 0x24040001, 0x24020005, 0x3c010001, 0xac2032b8, 0x10000102, 
-0xaee279c8, 0x3c040001, 0x2484308c, 0x3c05000f, 0x34a50100, 0x3021, 
-0x3821, 0xafa00010, 0xc0028eb, 0xafa00014, 0x100000f7, 0x0, 
-0x8f820220, 0x3c03f700, 0x431025, 0x100000ae, 0xaf820220, 0x8f820220, 
-0x3c030004, 0x431024, 0x144000bc, 0x24020007, 0x8f830054, 0x3c020001, 
-0x8c4233d0, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000e5, 0x24020001, 
-0x100000e1, 0x0, 0x3c050001, 0x8ca532ac, 0xc004785, 0x24040001, 
-0xc00484d, 0x24040001, 0x3c030001, 0x8c6354b4, 0x46100d7, 0x24020001, 
-0x3c020008, 0x621024, 0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 
-0x431024, 0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 
-0x3442241f, 0xaf820214, 0x8f820220, 0x3c030200, 0x283a025, 0x34420002, 
-0xaf820220, 0x24020008, 0xc003b1e, 0xaee279c8, 0x100000c1, 0x0, 
-0x8ee279c8, 0x2443ffff, 0x2c620008, 0x104000bc, 0x31080, 0x3c010001, 
-0x220821, 0x8c2230b8, 0x400008, 0x0, 0xc003a65, 0x0, 
-0x3c010001, 0xac2032b0, 0xaf800204, 0x3c010001, 0xc003f2b, 0xac205480, 
-0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0x34425080, 0xaf820044, 
-0x8f830054, 0x3c010001, 0xac203240, 0x10000062, 0x24020002, 0x3c020001, 
-0x8c4254b8, 0x30424000, 0x10400004, 0x0, 0x8f820044, 0x10000006, 
-0x3442f080, 0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, 
-0xaf820044, 0x8f830054, 0x10000051, 0x24020004, 0xc003b78, 0x0, 
-0x1040008d, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c8433c8, 
-0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x14800067, 0xaee279c8, 
-0x1000006c, 0x0, 0x8ee279c8, 0x2443ffff, 0x2c620007, 0x1040007e, 
-0x31080, 0x3c010001, 0x220821, 0x8c2230d8, 0x400008, 0x0, 
-0xc003a65, 0x0, 0x3c010001, 0xac2032b0, 0xaf800204, 0x3c010001, 
-0xc003f2b, 0xac205480, 0x8f830054, 0x3c010001, 0xac203240, 0x1000002a, 
-0x24020002, 0x8f830054, 0x3c020001, 0x8c4233d0, 0x2463d8f0, 0x431023, 
-0x2c422710, 0x14400064, 0x24020003, 0x10000062, 0xaee279c8, 0x3c020001, 
-0x8c4254b8, 0x30424000, 0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, 
-0x344201fe, 0xaf820238, 0x8f830054, 0x10000014, 0x24020004, 0x8f830054, 
-0x3c020001, 0x8c4233d0, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440004e, 
-0x24020005, 0x1000004c, 0xaee279c8, 0x8f820220, 0x3c03f700, 0x431025, 
-0xaf820220, 0xaf800204, 0x3c010001, 0xac205480, 0x8f830054, 0x24020006, 
-0xaee279c8, 0x3c010001, 0x1000003f, 0xac2333d0, 0x3c05fffe, 0x34a57960, 
-0x3c040001, 0x8f820054, 0x3c030001, 0x8c6333d0, 0x3484869f, 0x451021, 
-0x621823, 0x83202b, 0x10800033, 0x0, 0x24020007, 0x10000030, 
-0xaee279c8, 0xc003b78, 0x0, 0x1040002a, 0x24020001, 0x8f820214, 
-0x3c03ffff, 0x3c040001, 0x8c8433c8, 0x431024, 0x3442251f, 0xaf820214, 
-0x24020008, 0x1080000b, 0xaee279c8, 0x8f820220, 0x34420002, 0xaf820220, 
-0x24020001, 0x3c010001, 0xac225430, 0xc004430, 0x8f840220, 0x10000018, 
-0x0, 0x8f820220, 0x3c030008, 0x431024, 0x14400013, 0x3c020200, 
-0x282a025, 0x2402000e, 0x3c010001, 0xac225430, 0xc00484d, 0x24040001, 
-0x8f820220, 0x34420002, 0xc003b1e, 0xaf820220, 0x3c050001, 0x8ca532ac, 
-0xc004785, 0x24040001, 0x10000003, 0x0, 0x3c010001, 0xac2232b0, 
-0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 
-0x34420004, 0xaf820220, 0x8f820200, 0x3c040001, 0x8c8432ac, 0x34420004, 
-0xaf820200, 0x24020002, 0x1082003a, 0x2c820003, 0x10400005, 0x24020001, 
-0x1082000a, 0x3c03f0ff, 0x100000a8, 0x0, 0x24020004, 0x10820055, 
-0x24020008, 0x10820074, 0x3c02f0ff, 0x100000a1, 0x0, 0x8f820050, 
-0x3463ffff, 0x3c05ffff, 0x34a53f7f, 0x431024, 0x3c030700, 0x431025, 
-0xaf820050, 0x24020e00, 0xaf840200, 0xaf840220, 0xaf820238, 0x8f820044, 
-0x3c030001, 0x8c633298, 0x3c040001, 0x8c8433dc, 0x451024, 0x34630022, 
-0xaf820044, 0x24020004, 0x1082000c, 0xaf830200, 0x3c020001, 0x8c4232c0, 
-0x3c030001, 0x8c6332a4, 0x3c040001, 0x8c84329c, 0x34428000, 0x621825, 
-0x641825, 0x1000007e, 0x34620002, 0x3c020001, 0x8c4232a4, 0x3c030001, 
-0x8c6332c0, 0x3c040001, 0x8c84329c, 0x431025, 0x441025, 0x10000074, 
-0x34420002, 0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c8433c8, 
-0x621824, 0x3c020d00, 0x621825, 0x24020001, 0xaf830050, 0xaf820200, 
-0xaf820220, 0x24020e00, 0xaf820238, 0x10800005, 0x3c033f00, 0x3c020001, 
-0x8c423290, 0x10000004, 0x34630070, 0x3c020001, 0x8c423290, 0x34630072, 
-0x431025, 0xaf820200, 0x3c030001, 0x8c633294, 0x3c04f700, 0x3c020001, 
-0x8c4232a4, 0x3c050001, 0x8ca532c0, 0x641825, 0x431025, 0x10000050, 
-0x451025, 0x3c03f0ff, 0x8f820050, 0x3463ffff, 0x3c04ffff, 0x431024, 
-0x3c030a00, 0x431025, 0xaf820050, 0x24020001, 0xaf820200, 0xaf820220, 
-0x24020e01, 0xaf820238, 0x8f820044, 0x34843f7f, 0x3c030001, 0x8c6333c8, 
-0x441024, 0x34420080, 0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 
-0x8c423290, 0x10000004, 0x346300e0, 0x3c020001, 0x8c423290, 0x346300e2, 
-0x431025, 0xaf820200, 0x10000025, 0x3c05f700, 0x8f830050, 0x3c040001, 
-0x8c8433c8, 0x3442ffff, 0x621824, 0xaf830050, 0x10800013, 0x3c0500c8, 
-0x34a501fb, 0x3c063f00, 0x3c030001, 0x8c6332a0, 0x3c040001, 0x8c843290, 
-0x34c600e0, 0x24020001, 0xaf820200, 0xaf820220, 0xaf850238, 0x24630001, 
-0x862025, 0x3c010001, 0xac2332a0, 0xaf840200, 0x1000000b, 0x3c05f700, 
-0x3c0200c8, 0x344201fb, 0x3c030001, 0x8c633290, 0x3c043f00, 0x348400e2, 
-0xaf820238, 0x641825, 0xaf830200, 0x3c05f700, 0x34a58000, 0x3c030001, 
-0x8c633294, 0x3c020001, 0x8c4232a4, 0x3c040001, 0x8c8432c0, 0x651825, 
-0x431025, 0x441025, 0xaf820220, 0x3e00008, 0x0, 0x0, 
-0x27bdffd8, 0xafb50018, 0x80a821, 0xafbe001c, 0xa0f021, 0xafb30014, 
-0xc09821, 0xafb10010, 0x8821, 0xafbf0020, 0xa6600000, 0xc0043e7, 
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 
-0x2021, 0x24110010, 0x2b11024, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fffa, 0x2b11024, 0x24110010, 0x3d11024, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 
-0x3d11024, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7, 
-0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, 
-0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x0, 0x8fbf0020, 
-0x8fbe001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 
-0x27bdffd8, 0xafb30014, 0x809821, 0xafb50018, 0xa0a821, 0xafbe001c, 
-0xc0f021, 0xafb10010, 0x8821, 0xafbf0020, 0xc0043e7, 0x24040001, 
-0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 
-0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 
-0x24110010, 0x2711024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 
-0x118842, 0x1620fffa, 0x2711024, 0x24110010, 0x2b11024, 0x10400002, 
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x2b11024, 
-0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x97c20000, 
-0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 
-0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8fbf0020, 0x8fbe001c, 
-0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x3c030001, 
-0x8c6332d0, 0x3c020001, 0x8c423314, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 
-0x10620003, 0xafb10018, 0x3c010001, 0xac233314, 0x2463ffff, 0x2c620013, 
-0x10400349, 0x31080, 0x3c010001, 0x220821, 0x8c223100, 0x400008, 
-0x0, 0xc00440d, 0x8821, 0x34028000, 0xa7a20010, 0x27b30010, 
-0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 
-0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 
-0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 
-0xc0043e7, 0x2021, 0x118842, 0x1620fffc, 0x0, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 
-0x0, 0xc00440d, 0x0, 0x1000030e, 0x24020002, 0x27b30010, 
-0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 
-0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 
-0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, 0x32220001, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 
-0x32220001, 0x24110010, 0xc0043e7, 0x2021, 0x118842, 0x1620fffc, 
-0x0, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7, 
-0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, 
-0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x0, 0x97a20010, 
-0x30428000, 0x144002dc, 0x24020003, 0x100002d8, 0x0, 0x24021200, 
-0xa7a20010, 0x27b30010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, 
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 
-0x1620fffa, 0x32220001, 0x24110010, 0xc0043e7, 0x2021, 0x118842, 
-0x1620fffc, 0x0, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 
-0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 
-0x8f830054, 0x10000296, 0x24020004, 0x8f830054, 0x3c020001, 0x8c4233d8, 
-0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 
-0x8c6333dc, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003, 
-0x10620005, 0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 0x24020011, 
-0x1000028d, 0x24020005, 0x24020014, 0xa7a20010, 0x27b30010, 0x8821, 
-0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 
-0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 
-0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 
-0x32220012, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 
-0x1620fffa, 0x32220012, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 
-0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 
-0x8f830054, 0x10000248, 0x24020006, 0x8f830054, 0x3c020001, 0x8c4233d8, 
-0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, 0x24020007, 0x1000024c, 
-0x0, 0x24020006, 0xa7a20010, 0x27b30010, 0x8821, 0xc0043e7, 
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 
+0x1040fff0, 0x34028000, 0x1082ff57, 0x26310001, 0x2e220064, 0x1440ffb0, 
+0x0, 0x3c020001, 0x8c423408, 0x30420004, 0x14400007, 0x3c08fff0, 
+0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, 0x3c08fff0, 
+0x3508bdc0, 0x8f830054, 0x97a60018, 0x3c070001, 0x8ce7353c, 0x3c040001, 
+0x248431e0, 0x24020001, 0x3c010001, 0xac223410, 0xafa60010, 0x3c060001, 
+0x8cc63408, 0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001, 0xac20340c, 
+0x681821, 0x3c010001, 0xac233534, 0xc00290f, 0xafa20014, 0x8fbf0034, 
+0x8fb50030, 0x8fb3002c, 0x8fb10028, 0x3e00008, 0x27bd0038, 0x27bdffe8, 
+0x24070004, 0x3c040001, 0x8c84340c, 0x3021, 0x24020001, 0x1482000a, 
+0xafbf0010, 0x3c020001, 0x8c42561c, 0x3c050004, 0x30428000, 0x1040000c, 
+0x34a593e0, 0x3c05000f, 0x10000009, 0x34a54240, 0x3c020001, 0x8c42561c, 
+0x3c05000f, 0x30428000, 0x10400003, 0x34a54240, 0x3c05001e, 0x34a58480, 
+0x3c020001, 0x8c423534, 0x8f830054, 0x451021, 0x431023, 0x45102b, 
+0x1440002e, 0x0, 0x3c020001, 0x8c423414, 0x1440002a, 0x2cc20001, 
+0x7182b, 0x431024, 0x1040001d, 0x0, 0x3c090001, 0x8d293408, 
+0x240b0001, 0x3c054000, 0x3c080001, 0x2508561c, 0x250afffc, 0x42042, 
+0x14800002, 0x24e7ffff, 0x24040008, 0x891024, 0x5040000b, 0x2cc20001, 
+0x148b0004, 0x0, 0x8d020000, 0x10000003, 0x451024, 0x8d420000, 
+0x451024, 0x54400001, 0x24060001, 0x2cc20001, 0x7182b, 0x431024, 
+0x5440ffed, 0x42042, 0x3c010001, 0x10c00020, 0xac24340c, 0x8f830054, 
+0x24020001, 0x3c010001, 0xac223410, 0x3c010001, 0xac233534, 0x3c020001, 
+0x8c423410, 0x10400004, 0x24020001, 0x3c010001, 0xac203410, 0xaee279c8, 
+0x8ee379c8, 0x24020008, 0x10620005, 0x24020001, 0xc003e23, 0x0, 
+0x1000000b, 0x0, 0x3c030001, 0x8c63340c, 0x10620007, 0x2402000e, 
+0x3c030001, 0x8c635590, 0x10620003, 0x0, 0xc00447c, 0x8f840220, 
+0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c03fdff, 0x3c040001, 
+0x8c84340c, 0x3c020001, 0x8c423424, 0x3463ffff, 0x283a024, 0x14820006, 
+0xafbf0018, 0x8ee379c8, 0x3c020001, 0x8c423428, 0x10620006, 0x0, 
+0x8ee279c8, 0x3c010001, 0xac243424, 0x3c010001, 0xac223428, 0x3c030001, 
+0x8c63340c, 0x24020002, 0x10620139, 0x2c620003, 0x10400005, 0x24020001, 
+0x1062000a, 0x0, 0x10000131, 0x0, 0x24020004, 0x10620070, 
+0x24020008, 0x106200ac, 0x24020001, 0x1000012a, 0x0, 0x8ee279c8, 
+0x2443ffff, 0x2c620008, 0x10400127, 0x31080, 0x3c010001, 0x220821, 
+0x8c2231f8, 0x400008, 0x0, 0xc003f77, 0x0, 0x3c020001, 
+0x8c423418, 0x3c010001, 0xac2033a0, 0x104000e8, 0x24020002, 0xaee279c8, 
+0x3c010001, 0x10000116, 0xac203418, 0xc0040b7, 0x0, 0x3c030001, 
+0x8c633430, 0x24020011, 0x1462010f, 0x24020003, 0x100000aa, 0x0, 
+0x3c050001, 0x8ca5340c, 0x3c060001, 0x8cc6561c, 0xc0046cc, 0x24040001, 
+0x24020005, 0x3c010001, 0xac203418, 0x10000102, 0xaee279c8, 0x3c040001, 
+0x248431ec, 0x3c05000f, 0x34a50100, 0x3021, 0x3821, 0xafa00010, 
+0xc00290f, 0xafa00014, 0x100000f7, 0x0, 0x8f820220, 0x3c03f700, 
+0x431025, 0x100000ae, 0xaf820220, 0x8f820220, 0x3c030004, 0x431024, 
+0x144000bc, 0x24020007, 0x8f830054, 0x3c020001, 0x8c423530, 0x2463d8f0, 
+0x431023, 0x2c422710, 0x144000e5, 0x24020001, 0x100000e1, 0x0, 
+0x3c050001, 0x8ca5340c, 0xc0047d1, 0x24040001, 0xc004899, 0x24040001, 
+0x3c030001, 0x8c635614, 0x46100d7, 0x24020001, 0x3c020008, 0x621024, 
+0x10400006, 0x0, 0x8f820214, 0x3c03ffff, 0x431024, 0x10000005, 
+0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, 0xaf820214, 
+0x8f820220, 0x3c030200, 0x283a025, 0x34420002, 0xaf820220, 0x24020008, 
+0xc003b6a, 0xaee279c8, 0x100000c1, 0x0, 0x8ee279c8, 0x2443ffff, 
+0x2c620008, 0x104000bc, 0x31080, 0x3c010001, 0x220821, 0x8c223218, 
+0x400008, 0x0, 0xc003ab1, 0x0, 0x3c010001, 0xac203410, 
+0xaf800204, 0x3c010001, 0xc003f77, 0xac2055e0, 0x8f820044, 0x3c03ffff, 
+0x34633f7f, 0x431024, 0x34425080, 0xaf820044, 0x8f830054, 0x3c010001, 
+0xac2033a0, 0x10000062, 0x24020002, 0x3c020001, 0x8c425618, 0x30424000, 
+0x10400004, 0x0, 0x8f820044, 0x10000006, 0x3442f080, 0x8f820044, 
+0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, 0xaf820044, 0x8f830054, 
+0x10000051, 0x24020004, 0xc003bc4, 0x0, 0x1040008d, 0x24020001, 
+0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c843528, 0x431024, 0x3442251f, 
+0xaf820214, 0x24020008, 0x14800067, 0xaee279c8, 0x1000006c, 0x0, 
+0x8ee279c8, 0x2443ffff, 0x2c620007, 0x1040007e, 0x31080, 0x3c010001, 
+0x220821, 0x8c223238, 0x400008, 0x0, 0xc003ab1, 0x0, 
+0x3c010001, 0xac203410, 0xaf800204, 0x3c010001, 0xc003f77, 0xac2055e0, 
+0x8f830054, 0x3c010001, 0xac2033a0, 0x1000002a, 0x24020002, 0x8f830054, 
+0x3c020001, 0x8c423530, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400064, 
+0x24020003, 0x10000062, 0xaee279c8, 0x3c020001, 0x8c425618, 0x30424000, 
+0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, 0x344201fe, 0xaf820238, 
+0x8f830054, 0x10000014, 0x24020004, 0x8f830054, 0x3c020001, 0x8c423530, 
+0x2463d8f0, 0x431023, 0x2c422710, 0x1440004e, 0x24020005, 0x1000004c, 
+0xaee279c8, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, 
+0x3c010001, 0xac2055e0, 0x8f830054, 0x24020006, 0xaee279c8, 0x3c010001, 
+0x1000003f, 0xac233530, 0x3c05fffe, 0x34a57960, 0x3c040001, 0x8f820054, 
+0x3c030001, 0x8c633530, 0x3484869f, 0x451021, 0x621823, 0x83202b, 
+0x10800033, 0x0, 0x24020007, 0x10000030, 0xaee279c8, 0xc003bc4, 
+0x0, 0x1040002a, 0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, 
+0x8c843528, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0x1080000b, 
+0xaee279c8, 0x8f820220, 0x34420002, 0xaf820220, 0x24020001, 0x3c010001, 
+0xac225590, 0xc00447c, 0x8f840220, 0x10000018, 0x0, 0x8f820220, 
+0x3c030008, 0x431024, 0x14400013, 0x3c020200, 0x282a025, 0x2402000e, 
+0x3c010001, 0xac225590, 0xc004899, 0x24040001, 0x8f820220, 0x34420002, 
+0xc003b6a, 0xaf820220, 0x3c050001, 0x8ca5340c, 0xc0047d1, 0x24040001, 
+0x10000003, 0x0, 0x3c010001, 0xac223410, 0x8fbf0018, 0x3e00008, 
+0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, 
+0x8f820200, 0x3c040001, 0x8c84340c, 0x34420004, 0xaf820200, 0x24020002, 
+0x1082003a, 0x2c820003, 0x10400005, 0x24020001, 0x1082000a, 0x3c03f0ff, 
+0x100000a8, 0x0, 0x24020004, 0x10820055, 0x24020008, 0x10820074, 
+0x3c02f0ff, 0x100000a1, 0x0, 0x8f820050, 0x3463ffff, 0x3c05ffff, 
+0x34a53f7f, 0x431024, 0x3c030700, 0x431025, 0xaf820050, 0x24020e00, 
+0xaf840200, 0xaf840220, 0xaf820238, 0x8f820044, 0x3c030001, 0x8c6333f8, 
+0x3c040001, 0x8c84353c, 0x451024, 0x34630022, 0xaf820044, 0x24020004, 
+0x1082000c, 0xaf830200, 0x3c020001, 0x8c423420, 0x3c030001, 0x8c633404, 
+0x3c040001, 0x8c8433fc, 0x34428000, 0x621825, 0x641825, 0x1000007e, 
+0x34620002, 0x3c020001, 0x8c423404, 0x3c030001, 0x8c633420, 0x3c040001, 
+0x8c8433fc, 0x431025, 0x441025, 0x10000074, 0x34420002, 0x8f830050, 
+0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c843528, 0x621824, 0x3c020d00, 
+0x621825, 0x24020001, 0xaf830050, 0xaf820200, 0xaf820220, 0x24020e00, 
+0xaf820238, 0x10800005, 0x3c033f00, 0x3c020001, 0x8c4233f0, 0x10000004, 
+0x34630070, 0x3c020001, 0x8c4233f0, 0x34630072, 0x431025, 0xaf820200, 
+0x3c030001, 0x8c6333f4, 0x3c04f700, 0x3c020001, 0x8c423404, 0x3c050001, 
+0x8ca53420, 0x641825, 0x431025, 0x10000050, 0x451025, 0x3c03f0ff, 
+0x8f820050, 0x3463ffff, 0x3c04ffff, 0x431024, 0x3c030a00, 0x431025, 
+0xaf820050, 0x24020001, 0xaf820200, 0xaf820220, 0x24020e01, 0xaf820238, 
+0x8f820044, 0x34843f7f, 0x3c030001, 0x8c633528, 0x441024, 0x34420080, 
+0xaf820044, 0x10600005, 0x3c033f00, 0x3c020001, 0x8c4233f0, 0x10000004, 
+0x346300e0, 0x3c020001, 0x8c4233f0, 0x346300e2, 0x431025, 0xaf820200, 
+0x10000025, 0x3c05f700, 0x8f830050, 0x3c040001, 0x8c843528, 0x3442ffff, 
+0x621824, 0xaf830050, 0x10800013, 0x3c0500c8, 0x34a501fb, 0x3c063f00, 
+0x3c030001, 0x8c633400, 0x3c040001, 0x8c8433f0, 0x34c600e0, 0x24020001, 
+0xaf820200, 0xaf820220, 0xaf850238, 0x24630001, 0x862025, 0x3c010001, 
+0xac233400, 0xaf840200, 0x1000000b, 0x3c05f700, 0x3c0200c8, 0x344201fb, 
+0x3c030001, 0x8c6333f0, 0x3c043f00, 0x348400e2, 0xaf820238, 0x641825, 
+0xaf830200, 0x3c05f700, 0x34a58000, 0x3c030001, 0x8c6333f4, 0x3c020001, 
+0x8c423404, 0x3c040001, 0x8c843420, 0x651825, 0x431025, 0x441025, 
+0xaf820220, 0x3e00008, 0x0, 0x0, 0x27bdffd8, 0xafb50018, 
+0x80a821, 0xafbe001c, 0xa0f021, 0xafb30014, 0xc09821, 0xafb10010, 
+0x8821, 0xafbf0020, 0xa6600000, 0xc004433, 0x24040001, 0x26310001, 
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 
+0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010, 
+0x2b11024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fffa, 0x2b11024, 0x24110010, 0x3d11024, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x3d11024, 0xc004459, 
+0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, 
+0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, 
+0x0, 0xc004459, 0x0, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 
+0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb30014, 
+0x809821, 0xafb50018, 0xa0a821, 0xafbe001c, 0xc0f021, 0xafb10010, 
+0x8821, 0xafbf0020, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 
+0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 
+0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 0x2711024, 
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 
+0x2711024, 0x24110010, 0x2b11024, 0x10400002, 0x2021, 0x24040001, 
+0xc004433, 0x118842, 0x1620fffa, 0x2b11024, 0xc004433, 0x24040001, 
+0xc004433, 0x2021, 0x34118000, 0x97c20000, 0x511024, 0x10400002, 
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 
+0xc004459, 0x0, 0x8fbf0020, 0x8fbe001c, 0x8fb50018, 0x8fb30014, 
+0x8fb10010, 0x3e00008, 0x27bd0028, 0x3c030001, 0x8c633430, 0x3c020001, 
+0x8c423474, 0x27bdffd8, 0xafbf0020, 0xafb3001c, 0x10620003, 0xafb10018, 
+0x3c010001, 0xac233474, 0x2463ffff, 0x2c620013, 0x10400349, 0x31080, 
+0x3c010001, 0x220821, 0x8c223260, 0x400008, 0x0, 0xc004459, 
+0x8821, 0x34028000, 0xa7a20010, 0x27b30010, 0xc004433, 0x24040001, 
+0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 
+0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0xc004433, 0x2021, 
+0x118842, 0x1620fffc, 0x0, 0xc004433, 0x24040001, 0xc004433, 
+0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, 
+0x0, 0x1000030e, 0x24020002, 0x27b30010, 0xa7a00010, 0x8821, 
+0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 
+0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 0x24040001, 
+0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 
+0xc004433, 0x2021, 0x118842, 0x1620fffc, 0x0, 0xc004459, 
+0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, 
+0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, 
+0x0, 0xc004459, 0x0, 0x97a20010, 0x30428000, 0x144002dc, 
+0x24020003, 0x100002d8, 0x0, 0x24021200, 0xa7a20010, 0x27b30010, 
+0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 
+0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 
+0x24110010, 0xc004433, 0x2021, 0x118842, 0x1620fffc, 0x0, 
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 
+0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 0x10000296, 
+0x24020004, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x1440029e, 0x24020002, 0x3c030001, 0x8c63353c, 0x10620297, 
+0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004, 
+0x10620291, 0x2402000f, 0x1000028f, 0x24020011, 0x1000028d, 0x24020005, 
+0x24020014, 0xa7a20010, 0x27b30010, 0x8821, 0xc004433, 0x24040001, 
+0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 
+0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220012, 0x10400002, 
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220012, 
+0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 
+0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 0x10000248, 
+0x24020006, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x14400250, 0x24020007, 0x1000024c, 0x0, 0x24020006, 
+0xa7a20010, 0x27b30010, 0x8821, 0xc004433, 0x24040001, 0x26310001, 
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 
+0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 
+0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fffa, 0x32220001, 0x24110010, 0x32220013, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220013, 0xc004433, 
+0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024, 
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, 
+0x0, 0xc004459, 0x0, 0x8f830054, 0x10000207, 0x24020008, 
+0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, 
+0x1440020f, 0x24020009, 0x1000020b, 0x0, 0x27b30010, 0xa7a00010, 
+0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 
+0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, 
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 
+0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fffa, 0x32220018, 0xc004459, 0x34118000, 0xc004459, 
+0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000, 
+0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc004459, 
+0x8821, 0x97a20010, 0x27b30010, 0x34420001, 0xa7a20010, 0xc004433, 
+0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 
+0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 
 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220013, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 
-0x32220013, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, 
-0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 
-0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8f830054, 
-0x10000207, 0x24020008, 0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, 
-0x431023, 0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 0x0, 
-0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, 
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 
-0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220018, 0xc00440d, 
-0x34118000, 0xc00440d, 0x0, 0xc0043c7, 0x0, 0x50400005, 
+0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 
+0x32220018, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 
+0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 
+0x10000193, 0x2402000a, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 
+0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 0x0, 
+0x27b30010, 0xa7a00010, 0x8821, 0xc004433, 0x24040001, 0x26310001, 
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 
+0x24040001, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x24110010, 
+0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220017, 0xc004459, 
+0x34118000, 0xc004459, 0x0, 0xc004413, 0x0, 0x50400005, 
 0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, 
-0x0, 0xc00440d, 0x8821, 0x97a20010, 0x27b30010, 0x34420001, 
-0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
-0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 
-0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 
-0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 
-0x118842, 0x1620fffa, 0x32220018, 0xc0043e7, 0x24040001, 0xc0043e7, 
+0x0, 0xc004459, 0x8821, 0x97a20010, 0x27b30010, 0x34420700, 
+0xa7a20010, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 
+0x2021, 0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 
+0x24110010, 0x32220017, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fffa, 0x32220017, 0xc004433, 0x24040001, 0xc004433, 
 0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 
-0x0, 0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, 0x3c020001, 
-0x8c4233d8, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 
-0x10000197, 0x0, 0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 
+0x24040001, 0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, 
+0x0, 0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, 0x3c020001, 
+0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012, 
+0x10000123, 0x0, 0x27b30010, 0xa7a00010, 0x8821, 0xc004433, 
+0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 
+0x2021, 0xc004433, 0x24040001, 0xc004433, 0x24040001, 0xc004433, 
 0x2021, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 
-0x32220017, 0xc00440d, 0x34118000, 0xc00440d, 0x0, 0xc0043c7, 
+0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220014, 
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 
+0x32220014, 0xc004459, 0x34118000, 0xc004459, 0x0, 0xc004413, 
 0x0, 0x50400005, 0x118842, 0x96620000, 0x511025, 0xa6620000, 
-0x118842, 0x1620fff7, 0x0, 0xc00440d, 0x8821, 0x97a20010, 
-0x27b30010, 0x34420700, 0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, 
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 
-0x1620fffa, 0x32220001, 0x24110010, 0x32220017, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220017, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 
-0x0, 0xc00440d, 0x0, 0x8f830054, 0x1000011f, 0x2402000c, 
-0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, 0x431023, 0x2c420064, 
-0x14400127, 0x24020012, 0x10000123, 0x0, 0x27b30010, 0xa7a00010, 
-0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
-0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x2021, 0x24110010, 0x32220001, 0x10400002, 
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 
-0x24110010, 0x32220014, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 
-0x118842, 0x1620fffa, 0x32220014, 0xc00440d, 0x34118000, 0xc00440d, 
-0x0, 0xc0043c7, 0x0, 0x50400005, 0x118842, 0x96620000, 
-0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc00440d, 
-0x8821, 0x97a20010, 0x27b30010, 0x34420010, 0xa7a20010, 0xc0043e7, 
-0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 
-0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0xc0043e7, 
+0x118842, 0x1620fff7, 0x0, 0xc004459, 0x8821, 0x97a20010, 
+0x27b30010, 0x34420010, 0xa7a20010, 0xc004433, 0x24040001, 0x26310001, 
+0x2e220020, 0x1440fffb, 0x0, 0xc004433, 0x2021, 0xc004433, 
+0x24040001, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0x24110010, 
+0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fffa, 0x32220001, 0x24110010, 0x32220014, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220014, 0xc004433, 
+0x24040001, 0xc004433, 0x2021, 0x34118000, 0x96620000, 0x511024, 
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fff8, 
+0x0, 0xc004459, 0x0, 0x8f830054, 0x100000ab, 0x24020013, 
+0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 0x2c420064, 
+0x144000b3, 0x2402000d, 0x100000af, 0x0, 0x27b30010, 0xa7a00010, 
+0x8821, 0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
+0x0, 0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 
+0x24040001, 0xc004433, 0x2021, 0x24110010, 0x32220001, 0x10400002, 
+0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 
+0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fffa, 0x32220018, 0xc004459, 0x34118000, 0xc004459, 
+0x0, 0xc004413, 0x0, 0x50400005, 0x118842, 0x96620000, 
+0x511025, 0xa6620000, 0x118842, 0x1620fff7, 0x0, 0xc004459, 
+0x8821, 0x97a20010, 0x27b30010, 0x3042fffe, 0xa7a20010, 0xc004433, 
+0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 0xc004433, 
+0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0xc004433, 
 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220014, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 
-0x32220014, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x34118000, 
-0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 
-0x118842, 0x1620fff8, 0x0, 0xc00440d, 0x0, 0x8f830054, 
-0x100000ab, 0x24020013, 0x8f830054, 0x3c020001, 0x8c4233d8, 0x2463ff9c, 
-0x431023, 0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 0x0, 
-0x27b30010, 0xa7a00010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 
-0x2e220020, 0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 
-0x24040001, 0xc0043e7, 0x24040001, 0xc0043e7, 0x2021, 0x24110010, 
-0x32220001, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 
-0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220018, 0xc00440d, 
-0x34118000, 0xc00440d, 0x0, 0xc0043c7, 0x0, 0x50400005, 
-0x118842, 0x96620000, 0x511025, 0xa6620000, 0x118842, 0x1620fff7, 
-0x0, 0xc00440d, 0x8821, 0x97a20010, 0x27b30010, 0x3042fffe, 
-0xa7a20010, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 
-0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0xc0043e7, 
-0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 0x32220001, 
-0x24110010, 0x32220018, 0x10400002, 0x2021, 0x24040001, 0xc0043e7, 
-0x118842, 0x1620fffa, 0x32220018, 0xc0043e7, 0x24040001, 0xc0043e7, 
-0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 
-0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 0xc00440d, 
-0x0, 0x8f830054, 0x10000037, 0x2402000e, 0x24020840, 0xa7a20010, 
-0x27b30010, 0x8821, 0xc0043e7, 0x24040001, 0x26310001, 0x2e220020, 
-0x1440fffb, 0x0, 0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 
-0xc0043e7, 0x2021, 0xc0043e7, 0x24040001, 0x24110010, 0x32220001, 
-0x10400002, 0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fffa, 
-0x32220001, 0x24110010, 0x32220013, 0x10400002, 0x2021, 0x24040001, 
-0xc0043e7, 0x118842, 0x1620fffa, 0x32220013, 0xc0043e7, 0x24040001, 
-0xc0043e7, 0x2021, 0x34118000, 0x96620000, 0x511024, 0x10400002, 
-0x2021, 0x24040001, 0xc0043e7, 0x118842, 0x1620fff8, 0x0, 
-0xc00440d, 0x0, 0x8f830054, 0x24020010, 0x3c010001, 0xac2232d0, 
-0x3c010001, 0x1000000c, 0xac2333d8, 0x8f830054, 0x3c020001, 0x8c4233d8, 
-0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011, 
-0x3c010001, 0xac2232d0, 0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, 
-0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 
-0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, 0x10000002, 0x24840001, 
-0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 
-0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 
-0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 
-0x42480, 0x621824, 0x3c020002, 0x822025, 0x641825, 0xaf830044, 
-0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 
-0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 
-0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 
-0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x8f820044, 
-0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 
+0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 0x32220018, 
+0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 0x1620fffa, 
+0x32220018, 0xc004433, 0x24040001, 0xc004433, 0x2021, 0x34118000, 
+0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 0xc004433, 
+0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 0x8f830054, 
+0x10000037, 0x2402000e, 0x24020840, 0xa7a20010, 0x27b30010, 0x8821, 
+0xc004433, 0x24040001, 0x26310001, 0x2e220020, 0x1440fffb, 0x0, 
+0xc004433, 0x2021, 0xc004433, 0x24040001, 0xc004433, 0x2021, 
+0xc004433, 0x24040001, 0x24110010, 0x32220001, 0x10400002, 0x2021, 
+0x24040001, 0xc004433, 0x118842, 0x1620fffa, 0x32220001, 0x24110010, 
+0x32220013, 0x10400002, 0x2021, 0x24040001, 0xc004433, 0x118842, 
+0x1620fffa, 0x32220013, 0xc004433, 0x24040001, 0xc004433, 0x2021, 
+0x34118000, 0x96620000, 0x511024, 0x10400002, 0x2021, 0x24040001, 
+0xc004433, 0x118842, 0x1620fff8, 0x0, 0xc004459, 0x0, 
+0x8f830054, 0x24020010, 0x3c010001, 0xac223430, 0x3c010001, 0x1000000c, 
+0xac233538, 0x8f830054, 0x3c020001, 0x8c423538, 0x2463ff9c, 0x431023, 
+0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, 0xac223430, 
+0x8fbf0020, 0x8fb3001c, 0x8fb10018, 0x3e00008, 0x27bd0028, 0x8f850044, 
+0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, 0x8f840054, 
+0x8f820054, 0xa32824, 0x10000002, 0x24840001, 0x8f820054, 0x821023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 
+0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 
+0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c030001, 
 0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 
 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 
 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 
-0x0, 0x3e00008, 0x0, 0x0, 0x27bdffe8, 0xafbf0010, 
-0x8ee379c8, 0x24020008, 0x146201ca, 0x0, 0x3c020001, 0x8c4233c8, 
-0x14400005, 0x0, 0xc003a65, 0x8f840224, 0x100001c2, 0x0, 
-0x8f820220, 0x3c030008, 0x431024, 0x10400026, 0x24020001, 0x8f840224, 
-0x8f820220, 0x3c030400, 0x431024, 0x10400006, 0x0, 0x3c010001, 
-0xac205440, 0x3c010001, 0x1000000b, 0xac205460, 0x3c030001, 0x24635440, 
-0x8c620000, 0x24420001, 0xac620000, 0x2c420002, 0x14400003, 0x24020001, 
-0x3c010001, 0xac225460, 0x3c020001, 0x8c425460, 0x10400006, 0x30820040, 
-0x10400004, 0x24020001, 0x3c010001, 0x10000003, 0xac225464, 0x3c010001, 
-0xac205464, 0x3c010001, 0xac24543c, 0x3c010001, 0x1000000b, 0xac205470, 
-0x3c010001, 0xac225470, 0x3c010001, 0xac205460, 0x3c010001, 0xac205440, 
-0x3c010001, 0xac205464, 0x3c010001, 0xac20543c, 0x3c030001, 0x8c635430, 
-0x3c020001, 0x8c425434, 0x50620004, 0x2463ffff, 0x3c010001, 0xac235434, 
-0x2463ffff, 0x2c62000e, 0x1040017e, 0x31080, 0x3c010001, 0x220821, 
-0x8c223150, 0x400008, 0x0, 0x3c02fdff, 0x3442ffff, 0x282a024, 
-0x24020002, 0x3c010001, 0xac205460, 0x3c010001, 0xac205440, 0x3c010001, 
-0xac205470, 0x3c010001, 0xac20543c, 0x3c010001, 0xac205464, 0x3c010001, 
-0xac205458, 0x3c010001, 0xac205450, 0xaf800224, 0x3c010001, 0xac225430, 
-0xc003a65, 0x0, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 
-0xaf820200, 0x3c010001, 0xac205480, 0x8f830054, 0x3c020001, 0x8c425458, 
-0x24040001, 0x3c010001, 0xac24546c, 0x24420001, 0x3c010001, 0xac225458, 
-0x2c420004, 0x3c010001, 0xac235454, 0x14400006, 0x24020003, 0x3c010001, 
-0xac2432b0, 0x3c010001, 0x10000148, 0xac205458, 0x3c010001, 0x10000145, 
-0xac225430, 0x8f830054, 0x3c020001, 0x8c425454, 0x2463d8f0, 0x431023, 
-0x2c422710, 0x1440013d, 0x24020004, 0x3c010001, 0x1000013a, 0xac225430, 
-0x3c040001, 0x8c8433cc, 0x3c010001, 0xc004602, 0xac205448, 0x3c020001, 
-0x8c42547c, 0xaf820204, 0x8f820204, 0x30420030, 0x14400125, 0x24020002, 
-0x3c030001, 0x8c63547c, 0x24020005, 0x3c010001, 0xac225430, 0x3c010001, 
-0x10000126, 0xac235480, 0x3c020001, 0x8c425460, 0x10400122, 0x0, 
-0x3c020001, 0x8c42543c, 0x1040011e, 0x0, 0x3c010001, 0xac225468, 
-0x24020003, 0x3c010001, 0xac225440, 0x100000c1, 0x24020006, 0x3c010001, 
-0xac205448, 0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c425480, 
-0x24030007, 0x3c010001, 0xac235430, 0x34420040, 0x3c010001, 0xac225480, 
-0x3c020001, 0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, 
-0x104000f9, 0x24020002, 0x3c050001, 0x24a55440, 0x8ca20000, 0x2c424e21, 
-0x104000f3, 0x24020002, 0x3c020001, 0x8c425464, 0x104000f8, 0x2404ffbf, 
-0x3c020001, 0x8c42543c, 0x3c030001, 0x8c635468, 0x441024, 0x641824, 
-0x14430007, 0x24020001, 0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 
-0x100000ea, 0xac225430, 0x3c010001, 0x100000e7, 0xac225430, 0x3c020001, 
-0x8c42546c, 0x1040000c, 0x24020001, 0x3c040001, 0xc00460f, 0x8c84543c, 
-0x3c020001, 0x8c425488, 0x14400005, 0x24020001, 0x3c020001, 0x8c425484, 
-0x10400006, 0x24020001, 0x3c010001, 0xac2232b0, 0x3c010001, 0x100000d3, 
-0xac205458, 0x8f820204, 0x34420040, 0xaf820204, 0x3c020001, 0x8c425480, 
-0x3c030001, 0x8c635450, 0x34420040, 0x3c010001, 0xac225480, 0x3c020001, 
-0x8c42543c, 0x2c630001, 0x318c0, 0x3c010001, 0xac235450, 0x30420008, 
-0x3c010001, 0xac22544c, 0x8f830054, 0x24020009, 0x3c010001, 0xac225430, 
-0x3c010001, 0x100000b9, 0xac235454, 0x8f830054, 0x3c020001, 0x8c425454, 
-0x2463d8f0, 0x431023, 0x2c422710, 0x1440009f, 0x0, 0x3c020001, 
-0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, 0x104000a0, 
-0x24020002, 0x3c030001, 0x24635440, 0x8c620000, 0x2c424e21, 0x1040009a, 
-0x24020002, 0x3c020001, 0x8c42546c, 0x1040000e, 0x0, 0x3c020001, 
-0x8c42543c, 0x3c010001, 0xac20546c, 0x30420080, 0x1040002f, 0x2402000c, 
-0x8f820204, 0x30420080, 0x1440000c, 0x24020003, 0x10000029, 0x2402000c, 
-0x3c020001, 0x8c42543c, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 
-0x30420080, 0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 
-0xac225430, 0x3c040001, 0x24845478, 0x8c820000, 0x3c030001, 0x8c635450, 
-0x431025, 0xaf820204, 0x8c830000, 0x3c040001, 0x8c845450, 0x2402000b, 
-0x3c010001, 0xac225430, 0x641825, 0x3c010001, 0xac235480, 0x3c050001, 
-0x24a55440, 0x8ca20000, 0x2c424e21, 0x10400066, 0x24020002, 0x3c020001, 
-0x8c425470, 0x10400005, 0x0, 0x2402000c, 0x3c010001, 0x10000067, 
-0xac225430, 0x3c020001, 0x8c425460, 0x10400063, 0x0, 0x3c040001, 
-0x8c84543c, 0x10800055, 0x30820008, 0x3c030001, 0x8c63544c, 0x1062005b, 
-0x24020003, 0x3c010001, 0xac245468, 0xaca20000, 0x24020006, 0x3c010001, 
-0x10000054, 0xac225430, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 
-0x2402000d, 0x3c010001, 0xac225430, 0x3c010001, 0xac235454, 0x8f830054, 
-0x3c020001, 0x8c425454, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400031, 
-0x0, 0x3c020001, 0x8c425470, 0x10400020, 0x2402000e, 0x3c030001, 
-0x8c635484, 0x3c010001, 0x14600015, 0xac225430, 0xc003b1e, 0x0, 
-0x3c050001, 0x8ca532ac, 0xc004785, 0x24040001, 0x3c030001, 0x8c6332ac, 
-0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, 0x8c4232a8, 0x10000003, 
-0x2403fff7, 0x3c020001, 0x8c4232a8, 0x431024, 0x3c010001, 0xac2232a8, 
-0x8f830224, 0x3c020200, 0x3c010001, 0xac23548c, 0x10000020, 0x282a025, 
-0x3c020001, 0x8c425460, 0x10400005, 0x0, 0x3c020001, 0x8c42543c, 
-0x1040000f, 0x24020002, 0x3c020001, 0x8c425440, 0x2c424e21, 0x1040000a, 
-0x24020002, 0x3c020001, 0x8c425460, 0x1040000f, 0x0, 0x3c020001, 
-0x8c42543c, 0x1440000b, 0x0, 0x24020002, 0x3c010001, 0x10000007, 
-0xac225430, 0x3c020001, 0x8c425460, 0x10400003, 0x0, 0xc003a65, 
-0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 
-0x3e00008, 0x27bd0018, 0x3c030001, 0x24635488, 0x8c620000, 0x10400005, 
-0x34422000, 0x3c010001, 0xac22547c, 0x10000003, 0xac600000, 0x3c010001, 
-0xac24547c, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 
-0x3c010001, 0xac225484, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 
-0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02, 
-0x30820001, 0x21200, 0x3c040001, 0x8c8433cc, 0x621825, 0x331c2, 
-0x3c030001, 0x2463332c, 0x30828000, 0x21202, 0x30840001, 0x42200, 
-0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000, 
-0x24020001, 0x10620025, 0x0, 0x10600007, 0x24020002, 0x10620013, 
-0x24020003, 0x1062002c, 0x3c05000f, 0x10000037, 0x0, 0x8f820200, 
-0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 
-0x431024, 0xaf820220, 0x3c010001, 0xac2054c4, 0x3c010001, 0x10000034, 
-0xac2054cc, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 
-0x3463ffff, 0x431024, 0xaf820220, 0x24020100, 0x3c010001, 0xac2254c4, 
-0x3c010001, 0x10000026, 0xac2054cc, 0x8f820200, 0x2403feff, 0x431024, 
-0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 
-0xac2054c4, 0x3c010001, 0x10000019, 0xac2354cc, 0x8f820200, 0x34420100, 
-0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x24020100, 
-0x3c010001, 0xac2254c4, 0x3c010001, 0x1000000c, 0xac2354cc, 0x34a5ffff, 
-0x3c040001, 0x24843188, 0xafa30010, 0xc0028eb, 0xafa00014, 0x10000004, 
-0x0, 0x24020030, 0x3c010001, 0xac225488, 0x8fbf0018, 0x3e00008, 
-0x27bd0020, 0x0, 0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c, 
-0xa0f021, 0xafb10020, 0xc08821, 0x3c040001, 0x248431a0, 0x3c050009, 
-0x3c020001, 0x8c4232ac, 0x34a59001, 0x2603021, 0x3c03821, 0xafbf0030, 
-0xafb50028, 0xa7a0001a, 0xafb10014, 0xc0028eb, 0xafa20010, 0x24020002, 
-0x13c200e7, 0x2fc20003, 0x10400005, 0x24020001, 0x13c2000a, 0x3c02fffb, 
-0x100000e1, 0x0, 0x24020004, 0x13c2006d, 0x24020008, 0x13c2006c, 
-0x3c02ffec, 0x100000da, 0x0, 0x3442ffff, 0x2228824, 0x13a940, 
-0x3c010001, 0x350821, 0xac31549c, 0x3c024000, 0x2221024, 0x10400046, 
-0x1123c2, 0x30840030, 0x111382, 0x3042000c, 0x3c030001, 0x246332d4, 
-0x431021, 0x823821, 0x3c020020, 0x2221024, 0x10400006, 0x24020100, 
-0x3c010001, 0x350821, 0xac2254a0, 0x10000005, 0x3c020080, 0x3c010001, 
-0x350821, 0xac2054a0, 0x3c020080, 0x2221024, 0x10400006, 0x131940, 
-0x3c020001, 0x3c010001, 0x230821, 0x10000005, 0xac2254a8, 0x131140, 
-0x3c010001, 0x220821, 0xac2054a8, 0x94e30000, 0x32224000, 0x10400003, 
-0xa7a30018, 0x34624000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 
-0x24e60002, 0x34420001, 0xc00402a, 0xa4e20002, 0x24040001, 0x2821, 
-0xc00402a, 0x27a60018, 0x3c020001, 0x8c4232ac, 0x24130001, 0x3c010001, 
-0xac3332b8, 0x145e0004, 0x32228000, 0xc003a65, 0x0, 0x32228000, 
-0x10400093, 0x0, 0xc003a65, 0x0, 0x24020002, 0x3c010001, 
-0xac3332b0, 0x3c010001, 0x1000008b, 0xac2232ac, 0x24040001, 0x24050004, 
-0x27b1001a, 0xc00402a, 0x2203021, 0x24040001, 0x2821, 0xc00402a, 
-0x2203021, 0x3c020001, 0x551021, 0x8c425494, 0x3c040001, 0x8c8432ac, 
-0x3c03bfff, 0x3463ffff, 0x3c010001, 0xac3e32b8, 0x431024, 0x3c010001, 
-0x350821, 0x109e0072, 0xac225494, 0x10000072, 0x0, 0x3c02ffec, 
-0x3442ffff, 0x2228824, 0x3c020008, 0x2228825, 0x131140, 0x3c010001, 
-0x220821, 0xac315498, 0x3c022000, 0x2221024, 0x10400005, 0x24020001, 
-0x3c010001, 0xac2233c8, 0x10000004, 0x3c024000, 0x3c010001, 0xac2033c8, 
-0x3c024000, 0x2221024, 0x1440001a, 0x0, 0x3c020001, 0x8c4233c8, 
-0x10400005, 0x24022020, 0x3c010001, 0xac2233cc, 0x24020001, 0xaee279c8, 
-0x3c04bfff, 0x131940, 0x3c020001, 0x431021, 0x8c425490, 0x3c050001, 
-0x8ca532ac, 0x3484ffff, 0x441024, 0x3c010001, 0x230821, 0xac225490, 
-0x24020001, 0x10a20044, 0x0, 0x10000040, 0x0, 0x3c020001, 
-0x8c4233c8, 0x1040001c, 0x24022000, 0x3c010001, 0xac2233cc, 0x3c0300a0, 
-0x2231024, 0x14430005, 0x131140, 0x3402a000, 0x3c010001, 0x1000002d, 
-0xac2233cc, 0x3c030001, 0x621821, 0x8c635498, 0x3c020020, 0x621024, 
-0x10400004, 0x24022001, 0x3c010001, 0x10000023, 0xac2233cc, 0x3c020080, 
-0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, 0xac2233cc, 
-0x3c020020, 0x2221024, 0x10400007, 0x131940, 0x24020100, 0x3c010001, 
-0x230821, 0xac2254a4, 0x10000006, 0x3c020080, 0x131140, 0x3c010001, 
-0x220821, 0xac2054a4, 0x3c020080, 0x2221024, 0x10400006, 0x131940, 
-0x3c020001, 0x3c010001, 0x230821, 0x10000005, 0xac2254ac, 0x131140, 
-0x3c010001, 0x220821, 0xac2054ac, 0x3c030001, 0x8c6332ac, 0x24020001, 
-0x10620003, 0x0, 0xc003a65, 0x0, 0x8fbf0030, 0x8fbe002c, 
-0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffc8, 
-0xafb50028, 0xa821, 0xafbe002c, 0xf021, 0xafb30024, 0x9821, 
-0x24020002, 0xafbf0030, 0xafb10020, 0xafa4001c, 0xa7a00012, 0x10a2006a, 
-0xa7a00010, 0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, 0x3c024000, 
-0x100000ad, 0x2601021, 0x24020004, 0x10a20060, 0x24020008, 0x10a2005e, 
-0x2601021, 0x100000a6, 0x0, 0x8fa7001c, 0x78940, 0x3c030001, 
-0x711821, 0x8c63549c, 0x621024, 0x14400009, 0x24040001, 0x3c027fff, 
-0x3442ffff, 0x629824, 0x3c010001, 0x310821, 0xac335494, 0x10000096, 
-0x2601021, 0x24050001, 0xc003fe8, 0x27a60010, 0x24040001, 0x24050001, 
-0xc003fe8, 0x27a60010, 0x97a20010, 0x30420004, 0x10400034, 0x3c134000, 
-0x3c030001, 0x8c6333dc, 0x24020003, 0x10620008, 0x2c620004, 0x14400029, 
-0x3c028000, 0x24020004, 0x10620014, 0x24040001, 0x10000024, 0x3c028000, 
-0x24040001, 0x24050011, 0x27b10012, 0xc003fe8, 0x2203021, 0x24040001, 
-0x24050011, 0xc003fe8, 0x2203021, 0x97a30012, 0x30624000, 0x10400002, 
-0x3c1e0010, 0x3c1e0008, 0x3c150001, 0x10000010, 0x30628000, 0x24050014, 
-0x27b10012, 0xc003fe8, 0x2203021, 0x24040001, 0x24050014, 0xc003fe8, 
-0x2203021, 0x97a30012, 0x30621000, 0x10400002, 0x3c1e0010, 0x3c1e0008, 
-0x3c150001, 0x30620800, 0x54400001, 0x3c150002, 0x3c028000, 0x2621025, 
-0x2be1825, 0x10000007, 0x439825, 0x3c130001, 0x2719821, 0x8e73549c, 
-0x3c027fff, 0x3442ffff, 0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, 
-0x220821, 0xac335494, 0x1000004b, 0x2601021, 0x8fa7001c, 0x72140, 
-0x3c030001, 0x641821, 0x8c635498, 0x3c024000, 0x621024, 0x14400008, 
-0x3c027fff, 0x3442ffff, 0x629824, 0x3c010001, 0x240821, 0xac335490, 
-0x1000003b, 0x2601021, 0x3c020001, 0x8c4232bc, 0x1040002e, 0x3c13c00c, 
-0x3c020001, 0x8c4233c8, 0x3c03e00c, 0x3c010001, 0x240821, 0x8c2454a4, 
-0x2102b, 0x21023, 0x431024, 0x10800004, 0x539825, 0x3c020020, 
-0x10000004, 0x2629825, 0x3c02ffdf, 0x3442ffff, 0x2629824, 0x8fa7001c, 
-0x71140, 0x3c010001, 0x220821, 0x8c2254ac, 0x10400003, 0x3c020080, 
-0x10000004, 0x2629825, 0x3c02ff7f, 0x3442ffff, 0x2629824, 0x3c020001, 
-0x8c423320, 0x10400002, 0x3c020800, 0x2629825, 0x3c020001, 0x8c423324, 
-0x10400002, 0x3c020400, 0x2629825, 0x3c020001, 0x8c423328, 0x10400006, 
-0x3c020100, 0x10000004, 0x2629825, 0x3c027fff, 0x3442ffff, 0x629824, 
-0x8fa7001c, 0x71140, 0x3c010001, 0x220821, 0xac335490, 0x2601021, 
-0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 
-0x27bd0038, 0x27bdffe0, 0xafb50018, 0x80a821, 0xafbf001c, 0xafb30014, 
-0xafb10010, 0x8f840200, 0x3c030001, 0x8c6332ac, 0x8f860220, 0x24020002, 
-0x106200a3, 0x2c620003, 0x10400005, 0x24020001, 0x1062000a, 0x151940, 
-0x1000009d, 0x0, 0x24020004, 0x10620053, 0x24020008, 0x10620052, 
-0x159940, 0x10000096, 0x0, 0x3c050001, 0xa32821, 0x8ca5549c, 
-0x3c110001, 0x2238821, 0x8e315494, 0x3c024000, 0xa21024, 0x10400038, 
-0x3c020008, 0x2221024, 0x10400020, 0x34840002, 0x3c020001, 0x431021, 
-0x8c4254a0, 0x10400005, 0x34840020, 0x34840100, 0x3c020020, 0x10000006, 
-0x2228825, 0x2402feff, 0x822024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 
-0x151140, 0x3c010001, 0x220821, 0x8c2254a8, 0x10400005, 0x3c020001, 
-0xc23025, 0x3c020080, 0x10000016, 0x2228825, 0x3c02fffe, 0x3442ffff, 
-0xc23024, 0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2228824, 0x2402fedf, 
-0x822024, 0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff, 
-0x2228824, 0x3c010001, 0x230821, 0xac2054a0, 0x3c010001, 0x230821, 
-0xac2054a8, 0xaf840200, 0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 
-0x1000000a, 0x151140, 0x3c02bfff, 0x3442ffff, 0x8f830200, 0x2228824, 
-0x2402fffd, 0x621824, 0xc003a65, 0xaf830200, 0x151140, 0x3c010001, 
-0x220821, 0x10000048, 0xac315494, 0x159940, 0x3c050001, 0xb32821, 
-0x8ca55498, 0x3c110001, 0x2338821, 0x8e315490, 0x3c024000, 0xa21024, 
-0x14400010, 0x0, 0x3c020001, 0x8c4233c8, 0x14400005, 0x3c02bfff, 
-0x8f820200, 0x34420002, 0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003a65, 
-0x2228824, 0x3c010001, 0x330821, 0x1000002e, 0xac315490, 0x3c020001, 
-0x8c4233c8, 0x14400027, 0x151140, 0x3c020020, 0xa21024, 0x10400007, 
-0x34840020, 0x24020100, 0x3c010001, 0x330821, 0xac2254a4, 0x10000006, 
-0x34840100, 0x3c010001, 0x330821, 0xac2054a4, 0x2402feff, 0x822024, 
-0x3c020080, 0xa21024, 0x10400007, 0x151940, 0x3c020001, 0x3c010001, 
-0x230821, 0xac2254ac, 0x10000008, 0xc23025, 0x151140, 0x3c010001, 
-0x220821, 0xac2054ac, 0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, 
-0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 0x151140, 0x3c010001, 
-0x220821, 0xac315490, 0x8fbf001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 
-0x3e00008, 0x27bd0020, 0x0, 0x0, 0x1821, 0x308400ff, 
-0x2405ffdf, 0x2406ffbf, 0x641007, 0x30420001, 0x10400004, 0x0, 
-0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, 0xaf820044, 
-0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, 0x451024, 0xaf820044, 
-0x24630001, 0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 0x0, 
-0x0, 0x0, 0x0 };
-u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] = {
+0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 
+0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, 0xaf820044, 
+0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 
+0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 
+0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 
+0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 
+0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x8ee379c8, 0x24020008, 
+0x146201ca, 0x0, 0x3c020001, 0x8c423528, 0x14400005, 0x0, 
+0xc003ab1, 0x8f840224, 0x100001c2, 0x0, 0x8f820220, 0x3c030008, 
+0x431024, 0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 0x3c030400, 
+0x431024, 0x10400006, 0x0, 0x3c010001, 0xac2055a0, 0x3c010001, 
+0x1000000b, 0xac2055c0, 0x3c030001, 0x246355a0, 0x8c620000, 0x24420001, 
+0xac620000, 0x2c420002, 0x14400003, 0x24020001, 0x3c010001, 0xac2255c0, 
+0x3c020001, 0x8c4255c0, 0x10400006, 0x30820040, 0x10400004, 0x24020001, 
+0x3c010001, 0x10000003, 0xac2255c4, 0x3c010001, 0xac2055c4, 0x3c010001, 
+0xac24559c, 0x3c010001, 0x1000000b, 0xac2055d0, 0x3c010001, 0xac2255d0, 
+0x3c010001, 0xac2055c0, 0x3c010001, 0xac2055a0, 0x3c010001, 0xac2055c4, 
+0x3c010001, 0xac20559c, 0x3c030001, 0x8c635590, 0x3c020001, 0x8c425594, 
+0x50620004, 0x2463ffff, 0x3c010001, 0xac235594, 0x2463ffff, 0x2c62000e, 
+0x1040017e, 0x31080, 0x3c010001, 0x220821, 0x8c2232b0, 0x400008, 
+0x0, 0x3c02fdff, 0x3442ffff, 0x282a024, 0x24020002, 0x3c010001, 
+0xac2055c0, 0x3c010001, 0xac2055a0, 0x3c010001, 0xac2055d0, 0x3c010001, 
+0xac20559c, 0x3c010001, 0xac2055c4, 0x3c010001, 0xac2055b8, 0x3c010001, 
+0xac2055b0, 0xaf800224, 0x3c010001, 0xac225590, 0xc003ab1, 0x0, 
+0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, 
+0xac2055e0, 0x8f830054, 0x3c020001, 0x8c4255b8, 0x24040001, 0x3c010001, 
+0xac2455cc, 0x24420001, 0x3c010001, 0xac2255b8, 0x2c420004, 0x3c010001, 
+0xac2355b4, 0x14400006, 0x24020003, 0x3c010001, 0xac243410, 0x3c010001, 
+0x10000148, 0xac2055b8, 0x3c010001, 0x10000145, 0xac225590, 0x8f830054, 
+0x3c020001, 0x8c4255b4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440013d, 
+0x24020004, 0x3c010001, 0x1000013a, 0xac225590, 0x3c040001, 0x8c84352c, 
+0x3c010001, 0xc00464e, 0xac2055a8, 0x3c020001, 0x8c4255dc, 0xaf820204, 
+0x8f820204, 0x30420030, 0x14400125, 0x24020002, 0x3c030001, 0x8c6355dc, 
+0x24020005, 0x3c010001, 0xac225590, 0x3c010001, 0x10000126, 0xac2355e0, 
+0x3c020001, 0x8c4255c0, 0x10400122, 0x0, 0x3c020001, 0x8c42559c, 
+0x1040011e, 0x0, 0x3c010001, 0xac2255c8, 0x24020003, 0x3c010001, 
+0xac2255a0, 0x100000c1, 0x24020006, 0x3c010001, 0xac2055a8, 0x8f820204, 
+0x34420040, 0xaf820204, 0x3c020001, 0x8c4255e0, 0x24030007, 0x3c010001, 
+0xac235590, 0x34420040, 0x3c010001, 0xac2255e0, 0x3c020001, 0x8c4255c0, 
+0x10400005, 0x0, 0x3c020001, 0x8c42559c, 0x104000f9, 0x24020002, 
+0x3c050001, 0x24a555a0, 0x8ca20000, 0x2c424e21, 0x104000f3, 0x24020002, 
+0x3c020001, 0x8c4255c4, 0x104000f8, 0x2404ffbf, 0x3c020001, 0x8c42559c, 
+0x3c030001, 0x8c6355c8, 0x441024, 0x641824, 0x14430007, 0x24020001, 
+0x24020003, 0xaca20000, 0x24020008, 0x3c010001, 0x100000ea, 0xac225590, 
+0x3c010001, 0x100000e7, 0xac225590, 0x3c020001, 0x8c4255cc, 0x1040000c, 
+0x24020001, 0x3c040001, 0xc00465b, 0x8c84559c, 0x3c020001, 0x8c4255e8, 
+0x14400005, 0x24020001, 0x3c020001, 0x8c4255e4, 0x10400006, 0x24020001, 
+0x3c010001, 0xac223410, 0x3c010001, 0x100000d3, 0xac2055b8, 0x8f820204, 
+0x34420040, 0xaf820204, 0x3c020001, 0x8c4255e0, 0x3c030001, 0x8c6355b0, 
+0x34420040, 0x3c010001, 0xac2255e0, 0x3c020001, 0x8c42559c, 0x2c630001, 
+0x318c0, 0x3c010001, 0xac2355b0, 0x30420008, 0x3c010001, 0xac2255ac, 
+0x8f830054, 0x24020009, 0x3c010001, 0xac225590, 0x3c010001, 0x100000b9, 
+0xac2355b4, 0x8f830054, 0x3c020001, 0x8c4255b4, 0x2463d8f0, 0x431023, 
+0x2c422710, 0x1440009f, 0x0, 0x3c020001, 0x8c4255c0, 0x10400005, 
+0x0, 0x3c020001, 0x8c42559c, 0x104000a0, 0x24020002, 0x3c030001, 
+0x246355a0, 0x8c620000, 0x2c424e21, 0x1040009a, 0x24020002, 0x3c020001, 
+0x8c4255cc, 0x1040000e, 0x0, 0x3c020001, 0x8c42559c, 0x3c010001, 
+0xac2055cc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, 
+0x1440000c, 0x24020003, 0x10000029, 0x2402000c, 0x3c020001, 0x8c42559c, 
+0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 
+0x24020003, 0xac620000, 0x2402000a, 0x3c010001, 0xac225590, 0x3c040001, 
+0x248455d8, 0x8c820000, 0x3c030001, 0x8c6355b0, 0x431025, 0xaf820204, 
+0x8c830000, 0x3c040001, 0x8c8455b0, 0x2402000b, 0x3c010001, 0xac225590, 
+0x641825, 0x3c010001, 0xac2355e0, 0x3c050001, 0x24a555a0, 0x8ca20000, 
+0x2c424e21, 0x10400066, 0x24020002, 0x3c020001, 0x8c4255d0, 0x10400005, 
+0x0, 0x2402000c, 0x3c010001, 0x10000067, 0xac225590, 0x3c020001, 
+0x8c4255c0, 0x10400063, 0x0, 0x3c040001, 0x8c84559c, 0x10800055, 
+0x30820008, 0x3c030001, 0x8c6355ac, 0x1062005b, 0x24020003, 0x3c010001, 
+0xac2455c8, 0xaca20000, 0x24020006, 0x3c010001, 0x10000054, 0xac225590, 
+0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001, 
+0xac225590, 0x3c010001, 0xac2355b4, 0x8f830054, 0x3c020001, 0x8c4255b4, 
+0x2463d8f0, 0x431023, 0x2c422710, 0x14400031, 0x0, 0x3c020001, 
+0x8c4255d0, 0x10400020, 0x2402000e, 0x3c030001, 0x8c6355e4, 0x3c010001, 
+0x14600015, 0xac225590, 0xc003b6a, 0x0, 0x3c050001, 0x8ca5340c, 
+0xc0047d1, 0x24040001, 0x3c030001, 0x8c63340c, 0x24020004, 0x14620005, 
+0x2403fffb, 0x3c020001, 0x8c423408, 0x10000003, 0x2403fff7, 0x3c020001, 
+0x8c423408, 0x431024, 0x3c010001, 0xac223408, 0x8f830224, 0x3c020200, 
+0x3c010001, 0xac2355ec, 0x10000020, 0x282a025, 0x3c020001, 0x8c4255c0, 
+0x10400005, 0x0, 0x3c020001, 0x8c42559c, 0x1040000f, 0x24020002, 
+0x3c020001, 0x8c4255a0, 0x2c424e21, 0x1040000a, 0x24020002, 0x3c020001, 
+0x8c4255c0, 0x1040000f, 0x0, 0x3c020001, 0x8c42559c, 0x1440000b, 
+0x0, 0x24020002, 0x3c010001, 0x10000007, 0xac225590, 0x3c020001, 
+0x8c4255c0, 0x10400003, 0x0, 0xc003ab1, 0x0, 0x8f820220, 
+0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 
+0x3c030001, 0x246355e8, 0x8c620000, 0x10400005, 0x34422000, 0x3c010001, 
+0xac2255dc, 0x10000003, 0xac600000, 0x3c010001, 0xac2455dc, 0x3e00008, 
+0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010001, 0xac2255e4, 
+0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, 
+0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200, 
+0x3c040001, 0x8c84352c, 0x621825, 0x331c2, 0x3c030001, 0x2463348c, 
+0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, 
+0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, 
+0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c, 
+0x3c05000f, 0x10000037, 0x0, 0x8f820200, 0x2403feff, 0x431024, 
+0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 
+0x3c010001, 0xac205624, 0x3c010001, 0x10000034, 0xac20562c, 0x8f820200, 
+0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 
+0xaf820220, 0x24020100, 0x3c010001, 0xac225624, 0x3c010001, 0x10000026, 
+0xac20562c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 
+0x3c030001, 0x431025, 0xaf820220, 0x3c010001, 0xac205624, 0x3c010001, 
+0x10000019, 0xac23562c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 
+0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, 0xac225624, 
+0x3c010001, 0x1000000c, 0xac23562c, 0x34a5ffff, 0x3c040001, 0x248432e8, 
+0xafa30010, 0xc00290f, 0xafa00014, 0x10000004, 0x0, 0x24020030, 
+0x3c010001, 0xac2255e8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 
+0x27bdffc8, 0xafb30024, 0x809821, 0xafbe002c, 0xa0f021, 0xafb10020, 
+0xc08821, 0x3c040001, 0x24843300, 0x3c050009, 0x3c020001, 0x8c42340c, 
+0x34a59001, 0x2603021, 0x3c03821, 0xafbf0030, 0xafb50028, 0xa7a0001a, 
+0xafb10014, 0xc00290f, 0xafa20010, 0x24020002, 0x13c200e7, 0x2fc20003, 
+0x10400005, 0x24020001, 0x13c2000a, 0x3c02fffb, 0x100000e1, 0x0, 
+0x24020004, 0x13c2006d, 0x24020008, 0x13c2006c, 0x3c02ffec, 0x100000da, 
+0x0, 0x3442ffff, 0x2228824, 0x13a940, 0x3c010001, 0x350821, 
+0xac3155fc, 0x3c024000, 0x2221024, 0x10400046, 0x1123c2, 0x30840030, 
+0x111382, 0x3042000c, 0x3c030001, 0x24633434, 0x431021, 0x823821, 
+0x3c020020, 0x2221024, 0x10400006, 0x24020100, 0x3c010001, 0x350821, 
+0xac225600, 0x10000005, 0x3c020080, 0x3c010001, 0x350821, 0xac205600, 
+0x3c020080, 0x2221024, 0x10400006, 0x131940, 0x3c020001, 0x3c010001, 
+0x230821, 0x10000005, 0xac225608, 0x131140, 0x3c010001, 0x220821, 
+0xac205608, 0x94e30000, 0x32224000, 0x10400003, 0xa7a30018, 0x34624000, 
+0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, 0x24e60002, 0x34420001, 
+0xc004076, 0xa4e20002, 0x24040001, 0x2821, 0xc004076, 0x27a60018, 
+0x3c020001, 0x8c42340c, 0x24130001, 0x3c010001, 0xac333418, 0x145e0004, 
+0x32228000, 0xc003ab1, 0x0, 0x32228000, 0x10400093, 0x0, 
+0xc003ab1, 0x0, 0x24020002, 0x3c010001, 0xac333410, 0x3c010001, 
+0x1000008b, 0xac22340c, 0x24040001, 0x24050004, 0x27b1001a, 0xc004076, 
+0x2203021, 0x24040001, 0x2821, 0xc004076, 0x2203021, 0x3c020001, 
+0x551021, 0x8c4255f4, 0x3c040001, 0x8c84340c, 0x3c03bfff, 0x3463ffff, 
+0x3c010001, 0xac3e3418, 0x431024, 0x3c010001, 0x350821, 0x109e0072, 
+0xac2255f4, 0x10000072, 0x0, 0x3c02ffec, 0x3442ffff, 0x2228824, 
+0x3c020008, 0x2228825, 0x131140, 0x3c010001, 0x220821, 0xac3155f8, 
+0x3c022000, 0x2221024, 0x10400005, 0x24020001, 0x3c010001, 0xac223528, 
+0x10000004, 0x3c024000, 0x3c010001, 0xac203528, 0x3c024000, 0x2221024, 
+0x1440001a, 0x0, 0x3c020001, 0x8c423528, 0x10400005, 0x24022020, 
+0x3c010001, 0xac22352c, 0x24020001, 0xaee279c8, 0x3c04bfff, 0x131940, 
+0x3c020001, 0x431021, 0x8c4255f0, 0x3c050001, 0x8ca5340c, 0x3484ffff, 
+0x441024, 0x3c010001, 0x230821, 0xac2255f0, 0x24020001, 0x10a20044, 
+0x0, 0x10000040, 0x0, 0x3c020001, 0x8c423528, 0x1040001c, 
+0x24022000, 0x3c010001, 0xac22352c, 0x3c0300a0, 0x2231024, 0x14430005, 
+0x131140, 0x3402a000, 0x3c010001, 0x1000002d, 0xac22352c, 0x3c030001, 
+0x621821, 0x8c6355f8, 0x3c020020, 0x621024, 0x10400004, 0x24022001, 
+0x3c010001, 0x10000023, 0xac22352c, 0x3c020080, 0x621024, 0x1040001f, 
+0x3402a001, 0x3c010001, 0x1000001c, 0xac22352c, 0x3c020020, 0x2221024, 
+0x10400007, 0x131940, 0x24020100, 0x3c010001, 0x230821, 0xac225604, 
+0x10000006, 0x3c020080, 0x131140, 0x3c010001, 0x220821, 0xac205604, 
+0x3c020080, 0x2221024, 0x10400006, 0x131940, 0x3c020001, 0x3c010001, 
+0x230821, 0x10000005, 0xac22560c, 0x131140, 0x3c010001, 0x220821, 
+0xac20560c, 0x3c030001, 0x8c63340c, 0x24020001, 0x10620003, 0x0, 
+0xc003ab1, 0x0, 0x8fbf0030, 0x8fbe002c, 0x8fb50028, 0x8fb30024, 
+0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffc8, 0xafb50028, 0xa821, 
+0xafbe002c, 0xf021, 0xafb30024, 0x9821, 0x24020002, 0xafbf0030, 
+0xafb10020, 0xafa4001c, 0xa7a00012, 0x10a2006a, 0xa7a00010, 0x2ca20003, 
+0x10400005, 0x24020001, 0x10a2000a, 0x3c024000, 0x100000ad, 0x2601021, 
+0x24020004, 0x10a20060, 0x24020008, 0x10a2005e, 0x2601021, 0x100000a6, 
+0x0, 0x8fa7001c, 0x78940, 0x3c030001, 0x711821, 0x8c6355fc, 
+0x621024, 0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, 0x629824, 
+0x3c010001, 0x310821, 0xac3355f4, 0x10000096, 0x2601021, 0x24050001, 
+0xc004034, 0x27a60010, 0x24040001, 0x24050001, 0xc004034, 0x27a60010, 
+0x97a20010, 0x30420004, 0x10400034, 0x3c134000, 0x3c030001, 0x8c63353c, 
+0x24020003, 0x10620008, 0x2c620004, 0x14400029, 0x3c028000, 0x24020004, 
+0x10620014, 0x24040001, 0x10000024, 0x3c028000, 0x24040001, 0x24050011, 
+0x27b10012, 0xc004034, 0x2203021, 0x24040001, 0x24050011, 0xc004034, 
+0x2203021, 0x97a30012, 0x30624000, 0x10400002, 0x3c1e0010, 0x3c1e0008, 
+0x3c150001, 0x10000010, 0x30628000, 0x24050014, 0x27b10012, 0xc004034, 
+0x2203021, 0x24040001, 0x24050014, 0xc004034, 0x2203021, 0x97a30012, 
+0x30621000, 0x10400002, 0x3c1e0010, 0x3c1e0008, 0x3c150001, 0x30620800, 
+0x54400001, 0x3c150002, 0x3c028000, 0x2621025, 0x2be1825, 0x10000007, 
+0x439825, 0x3c130001, 0x2719821, 0x8e7355fc, 0x3c027fff, 0x3442ffff, 
+0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, 0x220821, 0xac3355f4, 
+0x1000004b, 0x2601021, 0x8fa7001c, 0x72140, 0x3c030001, 0x641821, 
+0x8c6355f8, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 
+0x629824, 0x3c010001, 0x240821, 0xac3355f0, 0x1000003b, 0x2601021, 
+0x3c020001, 0x8c42341c, 0x1040002e, 0x3c13c00c, 0x3c020001, 0x8c423528, 
+0x3c03e00c, 0x3c010001, 0x240821, 0x8c245604, 0x2102b, 0x21023, 
+0x431024, 0x10800004, 0x539825, 0x3c020020, 0x10000004, 0x2629825, 
+0x3c02ffdf, 0x3442ffff, 0x2629824, 0x8fa7001c, 0x71140, 0x3c010001, 
+0x220821, 0x8c22560c, 0x10400003, 0x3c020080, 0x10000004, 0x2629825, 
+0x3c02ff7f, 0x3442ffff, 0x2629824, 0x3c020001, 0x8c423480, 0x10400002, 
+0x3c020800, 0x2629825, 0x3c020001, 0x8c423484, 0x10400002, 0x3c020400, 
+0x2629825, 0x3c020001, 0x8c423488, 0x10400006, 0x3c020100, 0x10000004, 
+0x2629825, 0x3c027fff, 0x3442ffff, 0x629824, 0x8fa7001c, 0x71140, 
+0x3c010001, 0x220821, 0xac3355f0, 0x2601021, 0x8fbf0030, 0x8fbe002c, 
+0x8fb50028, 0x8fb30024, 0x8fb10020, 0x3e00008, 0x27bd0038, 0x27bdffe0, 
+0xafb50018, 0x80a821, 0xafbf001c, 0xafb30014, 0xafb10010, 0x8f840200, 
+0x3c030001, 0x8c63340c, 0x8f860220, 0x24020002, 0x106200a3, 0x2c620003, 
+0x10400005, 0x24020001, 0x1062000a, 0x151940, 0x1000009d, 0x0, 
+0x24020004, 0x10620053, 0x24020008, 0x10620052, 0x159940, 0x10000096, 
+0x0, 0x3c050001, 0xa32821, 0x8ca555fc, 0x3c110001, 0x2238821, 
+0x8e3155f4, 0x3c024000, 0xa21024, 0x10400038, 0x3c020008, 0x2221024, 
+0x10400020, 0x34840002, 0x3c020001, 0x431021, 0x8c425600, 0x10400005, 
+0x34840020, 0x34840100, 0x3c020020, 0x10000006, 0x2228825, 0x2402feff, 
+0x822024, 0x3c02ffdf, 0x3442ffff, 0x2228824, 0x151140, 0x3c010001, 
+0x220821, 0x8c225608, 0x10400005, 0x3c020001, 0xc23025, 0x3c020080, 
+0x10000016, 0x2228825, 0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff7f, 
+0x3442ffff, 0x1000000f, 0x2228824, 0x2402fedf, 0x822024, 0x3c02fffe, 
+0x3442ffff, 0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2228824, 0x3c010001, 
+0x230821, 0xac205600, 0x3c010001, 0x230821, 0xac205608, 0xaf840200, 
+0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, 0x151140, 
+0x3c02bfff, 0x3442ffff, 0x8f830200, 0x2228824, 0x2402fffd, 0x621824, 
+0xc003ab1, 0xaf830200, 0x151140, 0x3c010001, 0x220821, 0x10000048, 
+0xac3155f4, 0x159940, 0x3c050001, 0xb32821, 0x8ca555f8, 0x3c110001, 
+0x2338821, 0x8e3155f0, 0x3c024000, 0xa21024, 0x14400010, 0x0, 
+0x3c020001, 0x8c423528, 0x14400005, 0x3c02bfff, 0x8f820200, 0x34420002, 
+0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc003ab1, 0x2228824, 0x3c010001, 
+0x330821, 0x1000002e, 0xac3155f0, 0x3c020001, 0x8c423528, 0x14400027, 
+0x151140, 0x3c020020, 0xa21024, 0x10400007, 0x34840020, 0x24020100, 
+0x3c010001, 0x330821, 0xac225604, 0x10000006, 0x34840100, 0x3c010001, 
+0x330821, 0xac205604, 0x2402feff, 0x822024, 0x3c020080, 0xa21024, 
+0x10400007, 0x151940, 0x3c020001, 0x3c010001, 0x230821, 0xac22560c, 
+0x10000008, 0xc23025, 0x151140, 0x3c010001, 0x220821, 0xac20560c, 
+0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, 0xaf860220, 0x8f820220, 
+0x34420002, 0xaf820220, 0x151140, 0x3c010001, 0x220821, 0xac3155f0, 
+0x8fbf001c, 0x8fb50018, 0x8fb30014, 0x8fb10010, 0x3e00008, 0x27bd0020, 
+0x0, 0x0, 0x1821, 0x308400ff, 0x2405ffdf, 0x2406ffbf, 
+0x641007, 0x30420001, 0x10400004, 0x0, 0x8f820044, 0x10000003, 
+0x34420040, 0x8f820044, 0x461024, 0xaf820044, 0x8f820044, 0x34420020, 
+0xaf820044, 0x8f820044, 0x451024, 0xaf820044, 0x24630001, 0x28620008, 
+0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x0, 0x0, 
+0x0 };
+u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __init = {
 0x1, 0x1, 0x1, 0xc001fc, 0x3ffc, 0xc00000, 
 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x0, 0x0, 
 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x42424242, 0x0, 
@@ -5373,7 +5408,7 @@
 0x12000060, 0x12000180, 0x120001e0, 0x0, 0x0, 0x0, 
 0x0, 0x0, 0x0, 0x0, 0x30001, 0x1, 
 0x30201, 0x0, 0x0 };
-u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] = {
+u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __init = {
 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x66776d61, 
 0x696e2e63, 0x2c762031, 0x2e312e34, 0x372e3420, 0x31393938, 0x2f31302f, 
@@ -5429,12 +5464,14 @@
 0x0, 0x4d634465, 0x6c4e6f45, 0x0, 0x24486561, 0x6465723a, 
 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 
 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x646d612e, 0x632c7620, 0x312e312e, 
-0x31322e31, 0x20313939, 0x382f3038, 0x2f303420, 0x32313a35, 0x343a3339, 
+0x31322e33, 0x20313939, 0x382f3132, 0x2f303420, 0x32323a35, 0x313a3135, 
 0x20736875, 0x616e6720, 0x45787020, 0x24000000, 0x3f6e6f51, 0x64547845, 
 0x0, 0x3f6e6f51, 0x64527845, 0x0, 0x6576526e, 0x6746756c, 
 0x6c000000, 0x3f456e71, 0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 
 0x6661696c, 0x456e454d, 0x0, 0x656e714d, 0x45764661, 0x696c0000, 
 0x656e714d, 0x45765046, 0x61696c00, 0x646d6172, 0x6441544e, 0x0, 
+0x2a50414e, 0x49432a00, 0x2e2e2f2e, 0x2e2f2e2e, 0x2f2e2e2f, 0x2e2e2f73, 
+0x72632f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, 0x6e2f646d, 0x612e6300, 
 0x646d6177, 0x7241544e, 0x0, 0x0, 0x0, 0x0, 
 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 
 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x74726163, 
@@ -5444,9 +5481,9 @@
 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 0x6d6f6e2f, 0x64617461, 
 0x2e632c76, 0x20312e31, 0x2e322e34, 0x20313939, 0x382f3036, 0x2f323320, 
 0x30313a32, 0x393a3330, 0x20736875, 0x616e6720, 0x45787020, 0x24000000, 
-0x46575f56, 0x45525349, 0x4f4e3a20, 0x23312046, 0x7269204f, 0x63742031, 
-0x36203130, 0x3a31353a, 0x30362050, 0x44542031, 0x39393800, 0x46575f43, 
-0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031303a, 0x31353a30, 0x36000000, 
+0x46575f56, 0x45525349, 0x4f4e3a20, 0x2331204d, 0x6f6e2044, 0x65632037, 
+0x2031343a, 0x35383a32, 0x34205053, 0x54203139, 0x39380000, 0x46575f43, 
+0x4f4d5049, 0x4c455f54, 0x494d453a, 0x2031343a, 0x35383a32, 0x34000000, 
 0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 
 0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 
 0x0, 0x46575f43, 0x4f4d5049, 0x4c455f44, 0x4f4d4149, 0x4e3a2065, 
@@ -5469,20 +5506,20 @@
 0x756e6b72, 0x64747970, 0x65000000, 0x3f546370, 0x436b7375, 0x6d000000, 
 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 
-0x6d6f6e2f, 0x72656376, 0x2e632c76, 0x20312e31, 0x2e322e33, 0x35203139, 
-0x39382f30, 0x372f3239, 0x2030303a, 0x30373a32, 0x37207368, 0x75616e67, 
+0x6d6f6e2f, 0x72656376, 0x2e632c76, 0x20312e31, 0x2e34322e, 0x33203139, 
+0x39382f31, 0x322f3034, 0x2030303a, 0x31303a33, 0x38207368, 0x75616e67, 
 0x20457870, 0x20240000, 0x3f6e6f51, 0x64547845, 0x0, 0x3f6e6f51, 
 0x64527845, 0x0, 0x6576526e, 0x6746756c, 0x6c000000, 0x3f456e71, 
 0x45767400, 0x3f6e6f51, 0x64457650, 0x0, 0x6661696c, 0x456e454d, 
 0x0, 0x656e714d, 0x45764661, 0x696c0000, 0x656e714d, 0x45765046, 
 0x61696c00, 0x66726d32, 0x4c617267, 0x65000000, 0x72784e6f, 0x52784264, 
-0x0, 0x72785144, 0x6d614446, 0x0, 0x72785144, 0x6d614246, 
-0x0, 0x3f724264, 0x446d6146, 0x0, 0x3f724a42, 0x64446d46, 
-0x0, 0x0, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 
-0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 
-0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 0xdaac, 
-0xdaac, 0xdaac, 0xdabc, 0xdabc, 0xdabc, 0xdabc, 
-0xdabc, 0xdabc, 0x572d444d, 0x41456e46, 0x0, 0x0, 
+0x0, 0x72785144, 0x6d447446, 0x0, 0x72785144, 0x6d614446, 
+0x0, 0x72785144, 0x6d614246, 0x0, 0x3f724264, 0x446d6146, 
+0x0, 0x3f724a42, 0x64446d46, 0x0, 0xdbe8, 0xdbe8, 
+0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 
+0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 
+0xdbe8, 0xdbd8, 0xdbd8, 0xdbd8, 0xdbe8, 0xdbe8, 
+0xdbe8, 0xdbe8, 0xdbe8, 0xdbe8, 0x572d444d, 0x41456e46, 
 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 
 0x74732f72, 0x63732f73, 0x772f6765, 0x2f6e6963, 0x2f667732, 0x2f636f6d, 
 0x6d6f6e2f, 0x6d61632e, 0x632c7620, 0x312e312e, 0x31372e31, 0x20313939, 
@@ -5503,15 +5540,15 @@
 0x64457650, 0x0, 0x6661696c, 0x456e454d, 0x0, 0x656e714d, 
 0x45764661, 0x696c0000, 0x656e714d, 0x45765046, 0x61696c00, 0x0, 
 0x50726f62, 0x65506879, 0x0, 0x6c6e6b41, 0x53535254, 0x0, 
-0xf81c, 0xf84c, 0xf870, 0xf89c, 0xf8c8, 0xf8dc, 
-0xf918, 0xfca0, 0xf9c8, 0xfaf4, 0xfa14, 0xfb4c, 
-0xfb74, 0xfba8, 0xfa58, 0xfca0, 0xfac0, 0xfaf4, 
-0xfb1c, 0xfb4c, 0xfb74, 0xfba8, 0xfbe4, 0x0, 
-0x0, 0x0, 0x101fc, 0x102cc, 0x103a4, 0x10474, 
-0x104d0, 0x105ac, 0x105d4, 0x106b0, 0x106d8, 0x10880, 
-0x108a8, 0x10a50, 0x10c48, 0x10edc, 0x10df0, 0x10edc, 
-0x10f08, 0x10a78, 0x10c20, 0x0, 0x1120c, 0x11260, 
-0x112dc, 0x11308, 0x11358, 0x11394, 0x113c8, 0x11454, 
-0x1150c, 0x115dc, 0x1161c, 0x116a0, 0x116c4, 0x117d4, 
+0xf94c, 0xf97c, 0xf9a0, 0xf9cc, 0xf9f8, 0xfa0c, 
+0xfa48, 0xfdd0, 0xfaf8, 0xfc24, 0xfb44, 0xfc7c, 
+0xfca4, 0xfcd8, 0xfb88, 0xfdd0, 0xfbf0, 0xfc24, 
+0xfc4c, 0xfc7c, 0xfca4, 0xfcd8, 0xfd14, 0x0, 
+0x0, 0x0, 0x1032c, 0x103fc, 0x104d4, 0x105a4, 
+0x10600, 0x106dc, 0x10704, 0x107e0, 0x10808, 0x109b0, 
+0x109d8, 0x10b80, 0x10d78, 0x1100c, 0x10f20, 0x1100c, 
+0x11038, 0x10ba8, 0x10d50, 0x0, 0x1133c, 0x11390, 
+0x1140c, 0x11438, 0x11488, 0x114c4, 0x114f8, 0x11584, 
+0x1163c, 0x1170c, 0x1174c, 0x117d0, 0x117f4, 0x11904, 
 0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 
 0x73746d61, 0x634c4e4b, 0x0, 0x0, 0x0 };
diff -u --recursive --new-file v2.1.131/linux/drivers/net/apne.c linux/drivers/net/apne.c
--- v2.1.131/linux/drivers/net/apne.c	Mon Oct  5 13:13:39 1998
+++ linux/drivers/net/apne.c	Thu Dec 17 09:07:46 1998
@@ -119,22 +119,26 @@
 static const char *version =
     "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n";
 
+static int apne_owned = 0;	/* signal if card already owned */
 
 __initfunc(int apne_probe(struct device *dev))
 {
 #ifndef MANUAL_CONFIG
 	char tuple[8];
 #endif
+
+	if (apne_owned)
+		return -ENODEV;
         
 	if ( !(AMIGAHW_PRESENT(PCMCIA)) )
-		return (ENODEV);
+		return (-ENODEV);
                                 
 	printk("Looking for PCMCIA ethernet card : ");
                                         
 	/* check if a card is inserted */
 	if (!(PCMCIA_INSERTED)) {
 		printk("NO PCMCIA card inserted\n");
-		return (ENODEV);
+		return (-ENODEV);
 	}
                                                                                                 
 	/* disable pcmcia irq for readtuple */
@@ -144,7 +148,7 @@
 	if ((pcmcia_copy_tuple(CISTPL_FUNCID, tuple, 8) < 3) ||
 		(tuple[2] != CISTPL_FUNCID_NETWORK)) {
 		printk("not an ethernet card\n");
-		return (ENODEV);
+		return (-ENODEV);
 	}
 #endif
 
@@ -153,7 +157,7 @@
 	if (init_pcmcia())
 		return apne_probe1(dev, IOBASE+GAYLE_IO);
 	else
-		return (ENODEV);
+		return (-ENODEV);
 
 }
 
@@ -169,7 +173,7 @@
     int neX000, ctron;
 #endif
     static unsigned version_printed = 0;
-    static int pcmcia_offsets[16]={
+    static u32 pcmcia_offsets[16]={
                 0,   1+GAYLE_ODD,   2,   3+GAYLE_ODD,
                 4,   5+GAYLE_ODD,   6,   7+GAYLE_ODD,
                 8,   9+GAYLE_ODD, 0xa, 0xb+GAYLE_ODD,
@@ -197,7 +201,7 @@
 	while ((readb(ioaddr + NE_EN0_ISR) & ENISR_RESET) == 0)
 		if (jiffies - reset_start_time > 2*HZ/100) {
 			printk(" not found (no reset ack).\n");
-			return ENODEV;
+			return -ENODEV;
 		}
 
 	writeb(0xff, ioaddr + NE_EN0_ISR);		/* Ack all intr. */
@@ -328,6 +332,8 @@
     pcmcia_ack_int(pcmcia_get_intreq());		/* ack PCMCIA int req */
     pcmcia_enable_irq();
 
+    apne_owned = 1;
+
     return 0;
 }
 
@@ -390,7 +396,7 @@
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
 	printk("%s: DMAing conflict in ne_get_8390_hdr "
-	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
 	   dev->name, ei_status.dmaing, ei_status.irqlock,
 	   dev->interrupt);
 	return;
@@ -439,7 +445,7 @@
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
 	printk("%s: DMAing conflict in ne_block_input "
-	   "[DMAstat:%d][irqlock:%d][intr:%d].\n",
+	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
 	   dev->name, ei_status.dmaing, ei_status.irqlock,
 	   dev->interrupt);
 	return;
@@ -488,7 +494,7 @@
     /* This *shouldn't* happen. If it does, it's the last thing you'll see */
     if (ei_status.dmaing) {
 	printk("%s: DMAing conflict in ne_block_output."
-	   "[DMAstat:%d][irqlock:%d][intr:%d]\n",
+	   "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
 	   dev->name, ei_status.dmaing, ei_status.irqlock,
 	   dev->interrupt);
 	return;
@@ -577,15 +583,17 @@
 
 void cleanup_module(void)
 {
+	unregister_netdev(&apne_dev);
+
 	pcmcia_disable_irq();
 
 	free_irq(IRQ_AMIGA_PORTS, &apne_dev);
 
 	pcmcia_reset();
 
-	unregister_netdev(&apne_dev);
-
 	unlock_8390_module();
+
+	apne_owned = 0;
 }
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ariadne2.c linux/drivers/net/ariadne2.c
--- v2.1.131/linux/drivers/net/ariadne2.c	Thu Nov 12 16:21:19 1998
+++ linux/drivers/net/ariadne2.c	Thu Dec 17 09:07:46 1998
@@ -107,7 +107,7 @@
     unsigned char SA_prom[32];
     const char *name = NULL;
     int start_page, stop_page;
-    static int ariadne2_offsets[16] = {
+    static u32 ariadne2_offsets[16] = {
 	0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e,
 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
diff -u --recursive --new-file v2.1.131/linux/drivers/net/cosa.c linux/drivers/net/cosa.c
--- v2.1.131/linux/drivers/net/cosa.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/cosa.c	Thu Dec 17 09:04:49 1998
@@ -0,0 +1,1890 @@
+/* $Id: cosa.c,v 1.9 1998/12/08 02:24:23 kas Exp $ */
+
+/*
+ *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * The driver for the SRP and COSA synchronous serial cards.
+ *
+ * HARDWARE INFO
+ *
+ * Both cards are developed at the Institute of Computer Science,
+ * 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
+ * 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.
+ *
+ * The SRP (serial port?, the Czech word "srp" means "sickle") card
+ * is a 2-port intelligent (with its own 8-bit CPU) synchronous serial card
+ * with V.24 interfaces up to 80kb/s each.
+ *
+ * The COSA (communication serial adapter?, the Czech word "kosa" means
+ * "scythe") is a next-generation sync/async board with two interfaces
+ * - currently any of V.24, X.21, V.35 and V.36 can be selected.
+ * It has a 16-bit SAB80166 CPU and can do up to 10 Mb/s per channel.
+ * The 8-channels version is in development.
+ *
+ * Both types have downloadable firmware and communicate via ISA DMA.
+ * COSA can be also a bus-mastering device.
+ *
+ * SOFTWARE INFO
+ *
+ * The homepage of the Linux driver is at http://www.fi.muni.cz/~kas/cosa/.
+ * The CVS tree of Linux driver can be viewed there, as well as the
+ * firmware binaries and user-space utilities for downloading the firmware
+ * into the card and setting up the card.
+ *
+ * The Linux driver (unlike the present *BSD drivers :-) can work even
+ * for the COSA and SRP in one computer and allows each channel to work
+ * in one of the three modes (character device, Cisco HDLC, Sync PPP).
+ *
+ * AUTHOR
+ *
+ * The Linux driver was written by Jan "Yenya" Kasprzak <kas@fi.muni.cz>.
+ *
+ * You can mail me bugfixes and even success reports. I am especially
+ * interested in the SMP and/or muliti-channel success/failure reports
+ * (I wonder if I did the locking properly :-).
+ *
+ * THE AUTHOR USED THE FOLLOWING SOURCES WHEN PROGRAMMING THE DRIVER
+ *
+ * The COSA/SRP NetBSD driver by Zdenek Salvet and Ivos Cernohlavek
+ * The skeleton.c by Donald Becker
+ * The SDL Riscom/N2 driver by Mike Natale
+ * The Comtrol Hostess SV11 driver by Alan Cox
+ * The Sync PPP/Cisco HDLC layer (syncppp.c) ported to Linux by Alan Cox
+ */
+
+/* ---------- Headers, macros, data structures ---------- */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/poll.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+
+#undef COSA_SLOW_IO	/* for testing purposes only */
+#undef REALLY_SLOW_IO
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+#include <asm/spinlock.h>
+
+#include "syncppp.h"
+#include "cosa.h"
+
+/* Maximum length of the identification string. */
+#define COSA_MAX_ID_STRING	128
+
+/* Maximum length of the channel name */
+#define COSA_MAX_NAME		(sizeof("cosaXXXcXXX")+1)
+
+/* Per-channel data structure */
+
+struct channel_data {
+	int usage;	/* Usage count; >0 for chrdev, -1 for netdev */
+	int num;	/* Number of the channel */
+	struct cosa_data *cosa;	/* Pointer to the per-card structure */
+	int txsize;	/* Size of transmitted data */
+	char *txbuf;	/* Transmit buffer */
+	char name[COSA_MAX_NAME];	/* channel name */
+
+	/* The HW layer interface */
+	/* routine called from the RX interrupt */
+	char *(*setup_rx)(struct channel_data *channel, int size);
+	/* routine called when the RX is done (from the EOT interrupt) */
+	int (*rx_done)(struct channel_data *channel);
+	/* routine called when the TX is done (from the EOT interrupt) */
+	int (*tx_done)(struct channel_data *channel, int size);
+
+	/* Character device parts */
+	struct semaphore rsem, wsem;
+	char *rxdata;
+	int rxsize;
+	struct wait_queue *txwaitq, *rxwaitq;
+	int tx_status, rx_status;
+
+	/* SPPP/HDLC device parts */
+	struct ppp_device pppdev;
+	struct sk_buff *rx_skb, *tx_skb;
+	struct net_device_stats stats;
+};
+
+struct cosa_data {
+	int num;			/* Card number */
+	char name[COSA_MAX_NAME];	/* Card name - e.g "cosa0" */
+	unsigned int datareg, statusreg;	/* I/O ports */
+	unsigned short irq, dma;	/* IRQ and DMA number */
+	unsigned short startaddr;	/* Firmware start address */
+	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 usage;				/* usage count */
+	int txchan, txsize, rxsize;
+	struct channel_data *rxchan;
+	char *bouncebuf;
+	char *txbuf, *rxbuf;
+	struct channel_data *chan;
+	spinlock_t lock;	/* For exclusive operations on this structure */
+	char id_string[COSA_MAX_ID_STRING];	/* ROM monitor ID string */
+	char *type;				/* card type */
+};
+
+/*
+ * Define this if you want all the possible ports to be autoprobed.
+ * It is here but it probably is not a good idea to use this.
+ */
+/* #define COSA_ISA_AUTOPROBE	1 */
+
+/*
+ * Character device major number. 117 was allocated for us.
+ * The value of 0 means to allocate a first free one.
+ */
+static int cosa_major = 117;
+
+/*
+ * Encoding of the minor numbers:
+ * The lowest CARD_MINOR_BITS bits means the channel on the single card,
+ * the highest bits means the card number.
+ */
+#define CARD_MINOR_BITS	4	/* How many bits in minor number are reserved
+				 * for the single card */
+/*
+ * The following depends on CARD_MINOR_BITS. Unfortunately, the "MODULE_STRING"
+ * macro doesn't like anything other than the raw number as an argument :-(
+ */
+#define MAX_CARDS	16
+/* #define MAX_CARDS	(1 << (8-CARD_MINOR_BITS)) */
+
+#define DRIVER_RX_READY		0x0001
+#define DRIVER_TX_READY		0x0002
+#define DRIVER_TXMAP_SHIFT	2
+#define DRIVER_TXMAP_MASK	0x0c	/* FIXME: 0xfc for 8-channel version */
+
+/*
+ * for cosa->rxtx - indicates whether either transmit or receive is
+ * in progress. These values are mean number of the bit.
+ */
+#define TXBIT 0
+#define RXBIT 1
+#define IRQBIT 2
+
+#define COSA_MTU 2000	/* FIXME: I don't know this exactly */
+
+#undef DEBUG_DATA 1	/* Dump the data read or written to the channel */
+#undef DEBUG_IRQS 1	/* Print the message when the IRQ is received */
+#undef DEBUG_IO 1	/* Dump the I/O traffic */
+
+/* Maybe the following should be allocated dynamically */
+static struct cosa_data cosa_cards[MAX_CARDS];
+static int nr_cards = 0;
+
+#ifdef COSA_ISA_AUTOPROBE
+static int io[MAX_CARDS+1]  = { 0x220, 0x228, 0x210, 0x218, 0, };
+/* NOTE: DMA is not autoprobed!!! */
+static int dma[MAX_CARDS+1] = { 1, 7, 1, 7, 1, 7, 1, 7, 0, };
+#else
+int io[MAX_CARDS+1]  = { 0, };
+int dma[MAX_CARDS+1] = { 0, };
+#endif
+/* IRQ can be safely autoprobed */
+static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
+
+#ifdef MODULE
+MODULE_PARM(io, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM_DESC(io, "The I/O bases of the COSA or SRP cards");
+MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM_DESC(irq, "The IRQ lines of the COSA or SRP cards");
+MODULE_PARM(dma, "1-" __MODULE_STRING(MAX_CARDS) "i");
+MODULE_PARM_DESC(dma, "The DMA channels of the COSA or SRP cards");
+
+MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, <kas@fi.muni.cz>");
+MODULE_DESCRIPTION("Modular driver for the COSA or SRP synchronous card");
+#endif
+
+/* I use this mainly for testing purposes */
+#ifdef COSA_SLOW_IO
+#define cosa_outb outb_p
+#define cosa_outw outw_p
+#define cosa_inb  inb_p
+#define cosa_inw  inw_p
+#else
+#define cosa_outb outb
+#define cosa_outw outw
+#define cosa_inb  inb
+#define cosa_inw  inw
+#endif
+
+#define is_8bit(cosa)		(!(cosa->datareg & 0x08))
+
+#define cosa_getstatus(cosa)	(cosa_inb(cosa->statusreg))
+#define cosa_putstatus(cosa, stat)	(cosa_outb(stat, cosa->statusreg))
+#define cosa_getdata16(cosa)	(cosa_inw(cosa->datareg))
+#define cosa_getdata8(cosa)	(cosa_inb(cosa->datareg))
+#define cosa_putdata16(cosa, dt)	(cosa_outw(dt, cosa->datareg))
+#define cosa_putdata8(cosa, dt)	(cosa_outb(dt, cosa->datareg))
+
+/* Initialization stuff */
+static int cosa_probe(int ioaddr, int irq, int dma);
+
+/* HW interface */
+static void cosa_enable_rx(struct channel_data *chan);
+static void cosa_disable_rx(struct channel_data *chan);
+static int cosa_start_tx(struct channel_data *channel, char *buf, int size);
+static void cosa_kick(struct cosa_data *cosa);
+static int cosa_dma_able(struct channel_data *chan, char *buf, int data);
+
+/* SPPP/HDLC stuff */
+static void sppp_channel_init(struct channel_data *chan);
+static void sppp_channel_delete(struct channel_data *chan);
+static int cosa_sppp_open(struct device *d);
+static int cosa_sppp_close(struct device *d);
+static int cosa_sppp_tx(struct sk_buff *skb, struct device *d);
+static char *sppp_setup_rx(struct channel_data *channel, int size);
+static int sppp_rx_done(struct channel_data *channel);
+static int sppp_tx_done(struct channel_data *channel, int size);
+static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr, int cmd);
+static struct net_device_stats *cosa_net_stats(struct device *dev);
+
+/* Character device */
+static void chardev_channel_init(struct channel_data *chan);
+static char *chrdev_setup_rx(struct channel_data *channel, int size);
+static int chrdev_rx_done(struct channel_data *channel);
+static int chrdev_tx_done(struct channel_data *channel, int size);
+static long long cosa_lseek(struct file *file,
+	long long offset, int origin);
+static ssize_t cosa_read(struct file *file,
+	char *buf, size_t count, loff_t *ppos);
+static ssize_t cosa_write(struct file *file,
+	const char *buf, size_t count, loff_t *ppos);
+static unsigned int cosa_poll(struct file *file, poll_table *poll);
+static int cosa_open(struct inode *inode, struct file *file);
+static int cosa_release(struct inode *inode, struct file *file);
+static int cosa_chardev_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg);
+#ifdef COSA_FASYNC_WORKING
+static int cosa_fasync(struct inode *inode, struct file *file, int on);
+#endif
+
+static struct file_operations cosa_fops = {
+	cosa_lseek,
+	cosa_read,
+	cosa_write,
+	NULL,	/* readdir */
+	cosa_poll,
+	cosa_chardev_ioctl,
+	NULL,	/* mmap */
+	cosa_open,
+	NULL,	/* flush */
+	cosa_release,
+	NULL,	/* fsync */
+#ifdef COSA_FASYNC_WORKING
+	cosa_fasync,
+#else
+	NULL,
+#endif
+	NULL,	/* check media change */
+	NULL,	/* revalidate */
+	NULL	/* lock */
+};
+
+/* Ioctls */
+static int cosa_start(struct cosa_data *cosa, int address);
+static int cosa_reset(struct cosa_data *cosa);
+static int cosa_download(struct cosa_data *cosa, struct cosa_download *d);
+static int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d);
+
+/* COSA/SRP ROM monitor */
+static int download(struct cosa_data *cosa, char *data, int addr, int len);
+static int startmicrocode(struct cosa_data *cosa, int address);
+static int readmem(struct cosa_data *cosa, char *data, int addr, int len);
+static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
+
+/* Auxilliary functions */
+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)
+
+/* Interrupt handling */
+static void cosa_interrupt(int irq, void *cosa, struct pt_regs *regs);
+
+/* I/O ops debugging */
+#ifdef DEBUG_IO
+static void debug_data_in(struct cosa_data *cosa, int data);
+static void debug_data_out(struct cosa_data *cosa, int data);
+static void debug_data_cmd(struct cosa_data *cosa, int data);
+static void debug_status_in(struct cosa_data *cosa, int status);
+static void debug_status_out(struct cosa_data *cosa, int status);
+#endif
+
+
+/* ---------- Initialization stuff ---------- */
+
+#ifdef MODULE
+int init_module(void)
+#else
+__initfunc(static int cosa_init(void))
+#endif
+{
+	int i;
+	printk(KERN_INFO "cosa v1.02 (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
+	if (cosa_major > 0) {
+		if (register_chrdev(cosa_major, "cosa", &cosa_fops)) {
+			printk(KERN_WARNING "cosa: unable to get major %d\n",
+				cosa_major);
+			return -EIO;
+		}
+	} else {
+		if (!(cosa_major=register_chrdev(0, "cosa", &cosa_fops))) {
+			printk(KERN_WARNING "cosa: unable to register chardev\n");
+			return -EIO;
+		}
+	}
+	for (i=0; i<MAX_CARDS; i++)
+		cosa_cards[i].num = -1;
+	for (i=0; io[i] != 0 && i < MAX_CARDS; i++)
+		cosa_probe(io[i], irq[i], dma[i]);
+	if (!nr_cards) {
+		printk(KERN_WARNING "cosa: no devices found.\n");
+		unregister_chrdev(cosa_major, "cosa");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#ifdef MODULE
+void cleanup_module (void)
+{
+	struct cosa_data *cosa;
+	printk(KERN_INFO "Unloading the cosa module\n");
+
+	for (cosa=cosa_cards; nr_cards--; cosa++) {
+		int i;
+		/* Clean up the per-channel data */
+		for (i=0; i<cosa->nchannels; i++) {
+			/* Chardev driver has no alloc'd per-channel data */
+			sppp_channel_delete(cosa->chan+i);
+		}
+		/* Clean up the per-card data */
+		kfree(cosa->chan);
+		kfree(cosa->bouncebuf);
+		free_irq(cosa->irq, cosa);
+		free_dma(cosa->dma);
+		release_region(cosa->datareg,is_8bit(cosa)?2:4);
+	}
+	unregister_chrdev(cosa_major, "cosa");
+}
+#endif
+
+/*
+ * This function should register all the net devices needed for the
+ * single channel.
+ */
+static __inline__ void channel_init(struct channel_data *chan)
+{
+	sprintf(chan->name, "cosa%dc%d", chan->cosa->num, chan->num);
+
+	/* Initialize the chardev data structures */
+	chardev_channel_init(chan);
+
+	/* Register the sppp interface */
+	sppp_channel_init(chan);
+}
+	
+static int cosa_probe(int base, int irq, int dma)
+{
+	struct cosa_data *cosa = cosa_cards+nr_cards;
+	int i;
+
+	memset(cosa, 0, sizeof(struct cosa_data));
+
+	/* Checking validity of parameters: */
+	/* IRQ should be 2-7 or 10-15; negative IRQ means autoprobe */
+	if ((irq >= 0  && irq < 2) || irq > 15 || (irq < 10 && irq > 7)) {
+		printk (KERN_INFO "cosa_probe: invalid IRQ %d\n", irq);
+		return -1;
+	}
+	/* I/O address should be between 0x100 and 0x3ff and should be
+	 * multiple of 8. */
+	if (base < 0x100 || base > 0x3ff || base & 0x7) {
+		printk (KERN_INFO "cosa_probe: invalid I/O address 0x%x\n",
+			base);
+		return -1;
+	}
+	/* DMA should be 0,1 or 3-7 */
+	if (dma < 0 || dma == 4 || dma > 7) {
+		printk (KERN_INFO "cosa_probe: invalid DMA %d\n", dma);
+		return -1;
+	}
+	/* and finally, on 16-bit COSA DMA should be 4-7 and 
+	 * I/O base should not be multiple of 0x10 */
+	if (((base & 0x8) && dma < 4) || (!(base & 0x8) && dma > 3)) {
+		printk (KERN_INFO "cosa_probe: 8/16 bit base and DMA mismatch"
+			" (base=0x%x, dma=%d)\n", base, dma);
+		return -1;
+	}
+
+	cosa->dma = dma;
+	cosa->datareg = base;
+	cosa->statusreg = is_8bit(cosa)?base+1:base+2;
+	spin_lock_init(&cosa->lock);
+
+	if (check_region(base, is_8bit(cosa)?2:4))
+		return -1;
+	
+	if (cosa_reset_and_read_id(cosa, cosa->id_string) < 0) {
+		printk(KERN_DEBUG "cosa: probe at 0x%x failed.\n", base);
+		return -1;
+	}
+
+	/* Test the validity of identification string */
+	if (!strncmp(cosa->id_string, "SRP", 3))
+		cosa->type = "srp";
+	else if (!strncmp(cosa->id_string, "COSA", 4))
+		cosa->type = is_8bit(cosa)? "cosa8": "cosa16";
+	else {
+/* Print a warning only if we are not autoprobing */
+#ifndef COSA_ISA_AUTOPROBE
+		printk(KERN_INFO "cosa: valid signature not found at 0x%x.\n",
+			base);
+#endif
+		return -1;
+	}
+
+	/* Now do IRQ autoprobe */
+	if (irq < 0) {
+		unsigned long irqs;
+/*		printk(KERN_INFO "IRQ autoprobe\n"); */
+		sti();
+		irqs = probe_irq_on();
+		/* 
+		 * Enable interrupt on tx buffer empty (it sure is) 
+		 * really sure ?
+		 * FIXME: When this code is not used as module, we should
+		 * probably call udelay() instead of the interruptible sleep.
+		 */
+		current->state = TASK_INTERRUPTIBLE;
+		cosa_putstatus(cosa, SR_TX_INT_ENA);
+		schedule_timeout(30);
+		current->state = TASK_RUNNING;
+		irq = probe_irq_off(irqs);
+		/* Disable all IRQs from the card */
+		cosa_putstatus(cosa, 0);
+		/* Empty the received data register */
+		cosa_getdata8(cosa);
+
+		if (irq < 0) {
+			printk (KERN_INFO "cosa IRQ autoprobe: multiple interrupts obtained (%d, board at 0x%x)\n",
+				irq, cosa->datareg);
+			return -1;
+		}
+		if (irq == 0) {
+			printk (KERN_INFO "cosa IRQ autoprobe: no interrupt obtained (board at 0x%x)\n",
+				cosa->datareg);
+		/*	return -1; */
+		}
+	}
+
+	cosa->irq = irq;
+	cosa->num = nr_cards;
+	cosa->usage = 0;
+	cosa->nchannels = 2;	/* FIXME: how to determine this? */
+
+	request_region(base, is_8bit(cosa)?2:4, cosa->type);
+	if (request_irq(cosa->irq, cosa_interrupt, 0, cosa->type, cosa))
+		goto bad1;
+	if (request_dma(cosa->dma, cosa->type)) {
+		free_irq(cosa->irq, cosa);
+bad1:		release_region(cosa->datareg,is_8bit(cosa)?2:4);
+		printk(KERN_NOTICE "cosa%d: allocating resources failed\n",
+			cosa->num);
+		return -1;
+	}
+	
+	cosa->bouncebuf = kmalloc(COSA_MTU, GFP_KERNEL|GFP_DMA);
+	sprintf(cosa->name, "cosa%d", cosa->num);
+
+	/* Initialize the per-channel data */
+	cosa->chan = kmalloc(sizeof(struct channel_data)*cosa->nchannels,
+		GFP_KERNEL);
+	memset(cosa->chan, 0, sizeof(struct channel_data)*cosa->nchannels);
+	for (i=0; i<cosa->nchannels; i++) {
+		cosa->chan[i].cosa = cosa;
+		cosa->chan[i].num = i;
+		channel_init(cosa->chan+i);
+	}
+
+	printk (KERN_INFO "cosa%d: %s (%s at 0x%x irq %d dma %d), %d channels\n",
+		cosa->num, cosa->id_string, cosa->type,
+		cosa->datareg, cosa->irq, cosa->dma, cosa->nchannels);
+
+	return nr_cards++;
+}
+
+
+/*---------- SPPP/HDLC netdevice ---------- */
+
+static void sppp_channel_init(struct channel_data *chan)
+{
+	struct device *d;
+	sppp_attach(&chan->pppdev);
+	d=&chan->pppdev.dev;
+	d->name = chan->name;
+	d->base_addr = chan->cosa->datareg;
+	d->irq = chan->cosa->irq;
+	d->dma = chan->cosa->dma;
+	d->priv = chan;
+	d->init = NULL;
+	d->open = cosa_sppp_open;
+	d->stop = cosa_sppp_close;
+	d->hard_start_xmit = cosa_sppp_tx;
+	d->do_ioctl = cosa_sppp_ioctl;
+	d->get_stats = cosa_net_stats;
+	dev_init_buffers(d);
+	if (register_netdev(d) == -1) {
+		printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
+		sppp_detach(&chan->pppdev.dev);
+		return;
+	}
+}
+
+static void sppp_channel_delete(struct channel_data *chan)
+{
+	sppp_detach(&chan->pppdev.dev);
+	unregister_netdev(&chan->pppdev.dev);
+}
+
+
+static int cosa_sppp_open(struct device *d)
+{
+	struct channel_data *chan = d->priv;
+	int err, flags;
+
+	spin_lock_irqsave(&chan->cosa->lock, flags);
+	if (chan->usage != 0) {
+		printk(KERN_WARNING "%s: sppp_open called with usage count %d\n",
+			chan->name, chan->usage);
+		return -EBUSY;
+	}
+	chan->setup_rx = sppp_setup_rx;
+	chan->tx_done = sppp_tx_done;
+	chan->rx_done = sppp_rx_done;
+	chan->usage=-1;
+	chan->cosa->usage++;
+	MOD_INC_USE_COUNT;
+	spin_unlock_irqrestore(&chan->cosa->lock, flags);
+
+	err = sppp_open(d);
+	if (err) {
+		spin_lock_irqsave(&chan->cosa->lock, flags);
+		chan->usage=0;
+		chan->cosa->usage--;
+		MOD_DEC_USE_COUNT;
+		
+		spin_unlock_irqrestore(&chan->cosa->lock, flags);
+		return err;
+	}
+
+	d->tbusy = 0;
+	cosa_enable_rx(chan);
+	return 0;
+}
+
+static int cosa_sppp_tx(struct sk_buff *skb, struct device *dev)
+{
+	struct channel_data *chan = dev->priv;
+
+	if (dev->tbusy) { 
+		if (time_before(jiffies, dev->trans_start+2*HZ))
+			return 1;	/* Two seconds timeout */
+		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;
+		}
+		dev->tbusy = 0;
+	}
+	if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) {
+		printk(KERN_WARNING "%s: Transmitter access conflict.\n", dev->name);
+		return 1;
+	}
+	
+	chan->tx_skb = skb;
+	dev->trans_start = jiffies;
+	cosa_start_tx(chan, skb->data, skb->len);
+	return 0;
+}
+
+static int cosa_sppp_close(struct device *d)
+{
+	struct channel_data *chan = d->priv;
+	int flags;
+
+	sppp_close(d);
+	d->tbusy = 1;
+	cosa_disable_rx(chan);
+	spin_lock_irqsave(&chan->cosa->lock, flags);
+	chan->usage=0;
+	chan->cosa->usage--;
+	MOD_DEC_USE_COUNT;
+	spin_unlock_irqrestore(&chan->cosa->lock, flags);
+	return 0;
+}
+
+static char *sppp_setup_rx(struct channel_data *chan, int size)
+{
+	/*
+	 * We can safely fall back to non-dma-able memory, because we have
+	 * the cosa->bouncebuf pre-allocated.
+	 */
+	if (chan->rx_skb)
+		kfree_skb(chan->rx_skb);
+	chan->rx_skb = dev_alloc_skb(size);
+	if (chan->rx_skb == NULL) {
+		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet\n",
+			chan->name);
+		chan->stats.rx_dropped++;
+		return NULL;
+	}
+	chan->pppdev.dev.trans_start = jiffies;
+	return skb_put(chan->rx_skb, size);
+}
+
+static int sppp_rx_done(struct channel_data *chan)
+{
+	if (!chan->rx_skb) {
+		printk(KERN_WARNING "%s: rx_done with empty skb!\n",
+			chan->name);
+		chan->stats.rx_errors++;
+		chan->stats.rx_frame_errors++;
+		return 0;
+	}
+	chan->rx_skb->protocol = htons(ETH_P_WAN_PPP);
+	chan->rx_skb->dev = &chan->pppdev.dev;
+	chan->rx_skb->mac.raw = chan->rx_skb->data;
+	chan->stats.rx_packets++;
+	chan->stats.rx_bytes += chan->cosa->rxsize;
+	netif_rx(chan->rx_skb);
+	chan->rx_skb = 0;
+	chan->pppdev.dev.trans_start = jiffies;
+	return 0;
+}
+
+/* ARGSUSED */
+static int sppp_tx_done(struct channel_data *chan, int size)
+{
+	if (!chan->tx_skb) {
+		printk(KERN_WARNING "%s: tx_done with empty skb!\n",
+			chan->name);
+		chan->stats.tx_errors++;
+		chan->stats.tx_aborted_errors++;
+		return 1;
+	}
+	dev_kfree_skb(chan->tx_skb);
+	chan->tx_skb = 0;
+	chan->stats.tx_packets++;
+	chan->stats.tx_bytes += size;
+	chan->pppdev.dev.tbusy = 0;
+	mark_bh(NET_BH);
+	return 1;
+}
+
+static struct net_device_stats *cosa_net_stats(struct device *dev)
+{
+	struct channel_data *chan = dev->priv;
+	return &chan->stats;
+}
+
+
+/*---------- Character device ---------- */
+
+static void chardev_channel_init(struct channel_data *chan)
+{
+	chan->rsem = MUTEX;
+	chan->wsem = MUTEX;
+}
+
+static long long cosa_lseek(struct file * file,
+	long long offset, int origin)
+{
+	return -ESPIPE;
+}
+
+static ssize_t cosa_read(struct file *file,
+	char *buf, size_t count, loff_t *ppos)
+{
+	struct wait_queue wait = { current, NULL };
+	int flags;
+	struct channel_data *chan = (struct channel_data *)file->private_data;
+	struct cosa_data *cosa = chan->cosa;
+	char *kbuf;
+
+	if (down_interruptible(&chan->rsem))
+		return -ERESTARTSYS;
+	
+	if ((chan->rxdata = kmalloc(COSA_MTU, GFP_DMA|GFP_KERNEL)) == NULL) {
+		printk(KERN_INFO "%s: cosa_read() - OOM\n", cosa->name);
+		up(&chan->rsem);
+		return -ENOMEM;
+	}
+
+	chan->rx_status = 0;
+	cosa_enable_rx(chan);
+	spin_lock_irqsave(&cosa->lock, flags);
+	add_wait_queue(&chan->rxwaitq, &wait);
+	while(!chan->rx_status) {
+		current->state = TASK_INTERRUPTIBLE;
+		spin_unlock_irqrestore(&cosa->lock, flags);
+		schedule();
+		spin_lock_irqsave(&cosa->lock, flags);
+		if (signal_pending(current) && chan->rx_status == 0) {
+			chan->rx_status = 1;
+			remove_wait_queue(&chan->rxwaitq, &wait);
+			current->state = TASK_RUNNING;
+			spin_unlock_irqrestore(&cosa->lock, flags);
+			up(&chan->rsem);
+			return -ERESTARTSYS;
+		}
+	}
+	remove_wait_queue(&chan->rxwaitq, &wait);
+	current->state = TASK_RUNNING;
+	kbuf = chan->rxdata;
+	count = chan->rxsize;
+	spin_unlock_irqrestore(&cosa->lock, flags);
+	up(&chan->rsem);
+
+	if (copy_to_user(buf, kbuf, count)) {
+		kfree(buf);
+		return -EFAULT;
+	}
+	kfree(kbuf);
+	return count;
+}
+
+static char *chrdev_setup_rx(struct channel_data *chan, int size)
+{
+	/* Expect size <= COSA_MTU */
+	chan->rxsize = size;
+	return chan->rxdata;
+}
+
+static int chrdev_rx_done(struct channel_data *chan)
+{
+	if (chan->rx_status) { /* Reader has died */
+		kfree(chan->rxdata);
+		up(&chan->wsem);
+	}
+	chan->rx_status = 1;
+	wake_up_interruptible(&chan->rxwaitq);
+	return 1;
+}
+
+
+static ssize_t cosa_write(struct file *file,
+	const char *buf, size_t count, loff_t *ppos)
+{
+	struct channel_data *chan = (struct channel_data *)file->private_data;
+	struct wait_queue wait = { current, NULL };
+	struct cosa_data *cosa = chan->cosa;
+	unsigned int flags;
+	char *kbuf;
+
+	if (down_interruptible(&chan->wsem))
+		return -ERESTARTSYS;
+
+	if (count > COSA_MTU)
+		count = COSA_MTU;
+	
+	/* Allocate the buffer */
+	if ((kbuf = kmalloc(count, GFP_KERNEL|GFP_DMA)) == NULL) {
+		printk(KERN_NOTICE "%s: cosa_write() OOM - dropping packet\n",
+			cosa->name);
+		up(&chan->wsem);
+		return -ENOMEM;
+	}
+	if (copy_from_user(kbuf, buf, count)) {
+		up(&chan->wsem);
+		kfree(kbuf);
+		return -EFAULT;
+	}
+	chan->tx_status=0;
+	cosa_start_tx(chan, kbuf, count);
+
+	spin_lock_irqsave(&cosa->lock, flags);
+	add_wait_queue(&chan->txwaitq, &wait);
+	while(!chan->tx_status) {
+		current->state = TASK_INTERRUPTIBLE;
+		spin_unlock_irqrestore(&cosa->lock, flags);
+		schedule();
+		spin_lock_irqsave(&cosa->lock, flags);
+		if (signal_pending(current) && chan->tx_status == 0) {
+			chan->tx_status = 1;
+			remove_wait_queue(&chan->txwaitq, &wait);
+			current->state = TASK_RUNNING;
+			chan->tx_status = 1;
+			spin_unlock_irqrestore(&cosa->lock, flags);
+			return -ERESTARTSYS;
+		}
+	}
+	remove_wait_queue(&chan->txwaitq, &wait);
+	current->state = TASK_RUNNING;
+	up(&chan->wsem);
+	spin_unlock_irqrestore(&cosa->lock, flags);
+	kfree(kbuf);
+	return count;
+}
+
+static int chrdev_tx_done(struct channel_data *chan, int size)
+{
+	if (chan->tx_status) { /* Writer was interrupted */
+		kfree(chan->txbuf);
+		up(&chan->wsem);
+	}
+	chan->tx_status = 1;
+	wake_up_interruptible(&chan->txwaitq);
+	return 1;
+}
+
+static unsigned int cosa_poll(struct file *file, poll_table *poll)
+{
+	printk(KERN_INFO "cosa_poll is here\n");
+	return 0;
+}
+
+static int cosa_open(struct inode *inode, struct file *file)
+{
+	struct cosa_data *cosa;
+	struct channel_data *chan;
+	unsigned long flags;
+	int n;
+
+	if ((n=MINOR(file->f_dentry->d_inode->i_rdev)>>CARD_MINOR_BITS)
+		>= nr_cards)
+		return -ENODEV;
+	cosa = cosa_cards+n;
+
+	if ((n=MINOR(file->f_dentry->d_inode->i_rdev)
+		& ((1<<CARD_MINOR_BITS)-1)) >= cosa->nchannels)
+		return -ENODEV;
+	chan = cosa->chan + n;
+	
+	file->private_data = chan;
+
+	spin_lock_irqsave(&cosa->lock, flags);
+
+	if (chan->usage < 0) { /* in netdev mode */
+		spin_unlock_irqrestore(&cosa->lock, flags);
+		return -EBUSY;
+	}
+	cosa->usage++;
+	chan->usage++;
+
+	chan->tx_done = chrdev_tx_done;
+	chan->setup_rx = chrdev_setup_rx;
+	chan->rx_done = chrdev_rx_done;
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	spin_unlock_irqrestore(&cosa->lock, flags);
+	return 0;
+}
+
+static int cosa_release(struct inode *inode, struct file *file)
+{
+	struct channel_data *channel = (struct channel_data *)file->private_data;
+	struct cosa_data *cosa = channel->cosa;
+	unsigned long flags;
+
+	spin_lock_irqsave(&cosa->lock, flags);
+	cosa->usage--;
+	channel->usage--;
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+	spin_unlock_irqrestore(&cosa->lock, flags);
+	return 0;
+}
+
+#ifdef COSA_FASYNC_WORKING
+static struct fasync_struct *fasync[256] = { NULL, };
+
+/* To be done ... */
+static int cosa_fasync(struct inode *inode, struct file *file, int on)
+{
+        int port = MINOR(inode->i_rdev);
+        int rv = fasync_helper(inode, file, on, &fasync[port]);
+        return rv < 0 ? rv : 0;
+}
+#endif
+
+
+/* ---------- Ioctls ---------- */
+
+/*
+ * Ioctl subroutines can safely be made inline, because they are called
+ * only from cosa_ioctl().
+ */
+static inline int cosa_reset(struct cosa_data *cosa)
+{
+	char idstring[COSA_MAX_ID_STRING];
+	if (cosa->usage > 1)
+		printk(KERN_INFO "cosa%d: WARNING: reset requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+			cosa->num, cosa->usage);
+	if (cosa_reset_and_read_id(cosa, idstring) < 0) {
+		printk(KERN_NOTICE "cosa%d: reset failed\n", cosa->num);
+		return -EIO;
+	}
+	printk(KERN_INFO "cosa%d: resetting device: %s\n", cosa->num,
+		idstring);
+	return 0;
+}
+
+/* High-level function to download data into COSA memory. Calls download() */
+static inline int cosa_download(struct cosa_data *cosa, struct cosa_download *d)
+{
+	int i;
+	int addr, len;
+	char *code;
+
+	if (cosa->usage > 1)
+		printk(KERN_INFO "cosa%d: WARNING: download of microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+			cosa->num, cosa->usage);
+#if 0
+	if (cosa->status != CARD_STATUS_RESETED && cosa->status != CARD_STATUS_DOWNLOADED) {
+		printk(KERN_NOTICE "cosa%d: reset the card first (status %d).\n",
+			cosa->num, cosa->status);
+		return -EPERM;
+	}
+#endif
+	get_user_ret(addr, &(d->addr), -EFAULT);
+	get_user_ret(len, &(d->len), -EFAULT);
+	get_user_ret(code, &(d->code), -EFAULT);
+
+	if (d->len < 0)
+		return -EINVAL;
+
+	if ((i=download(cosa, d->code, len, addr)) < 0) {
+		printk(KERN_NOTICE "cosa%d: microcode download failed: %d\n",
+			cosa->num, i);
+		return -EIO;
+	}
+	printk(KERN_INFO "cosa%d: downloading microcode - 0x%04x bytes at 0x%04x\n",
+		cosa->num, len, addr);
+	return 0;
+}
+
+/* High-level function to read COSA memory. Calls readmem() */
+static inline int cosa_readmem(struct cosa_data *cosa, struct cosa_download *d)
+{
+	int i;
+	int addr, len;
+	char *code;
+
+	if (cosa->usage > 1)
+		printk(KERN_INFO "cosa%d: WARNING: readmem requested with "
+			"cosa->usage > 1 (%d). Odd things may happen.\n",
+			cosa->num, cosa->usage);
+#if 0
+	if (cosa->status != CARD_STATUS_RESETED &&
+		cosa->status != CARD_STATUS_DOWNLOADED) {
+		printk(KERN_NOTICE "cosa%d: reset the card first (status %d).\n",
+			cosa->num, cosa->status);
+		return -EPERM;
+	}
+#endif
+	get_user_ret(addr, &(d->addr), -EFAULT);
+	get_user_ret(len, &(d->len), -EFAULT);
+	get_user_ret(code, &(d->code), -EFAULT);
+
+	if ((i=readmem(cosa, d->code, len, addr)) < 0) {
+		printk(KERN_NOTICE "cosa%d: reading memory failed: %d\n",
+			cosa->num, i);
+		return -EIO;
+	}
+	printk(KERN_INFO "cosa%d: reading card memory - 0x%04x bytes at 0x%04x\n",
+		cosa->num, len, addr);
+	return 0;
+}
+
+/* High-level function to start microcode. Calls startmicrocode(). */
+static inline int cosa_start(struct cosa_data *cosa, int address)
+{
+	int i;
+
+	if (cosa->usage > 1)
+		printk(KERN_INFO "cosa%d: WARNING: start microcode requested with cosa->usage > 1 (%d). Odd things may happen.\n",
+			cosa->num, cosa->usage);
+#if 0
+	if (cosa->status != CARD_STATUS_DOWNLOADED) {
+		printk(KERN_NOTICE "cosa%d: download the microcode first (status %d).\n",
+			cosa->num, cosa->status);
+		return -EPERM;
+	}
+#endif
+	if ((i=startmicrocode(cosa, address)) < 0) {
+		printk(KERN_NOTICE "cosa%d: start microcode at 0x%04x failed: %d\n",
+			cosa->num, address, i);
+		return -EIO;
+	}
+	printk(KERN_INFO "cosa%d: starting microcode at 0x%04x\n",
+		cosa->num, address);
+	cosa->startaddr = address;
+	return 0;
+}
+		
+/* Buffer of size at least COSA_MAX_ID_STRING is expected */
+static inline int cosa_getidstr(struct cosa_data *cosa, char *string)
+{
+	int l = strlen(cosa->id_string)+1;
+	copy_to_user_ret(string, cosa->id_string, l, -EFAULT);
+	return l;
+}
+
+/* Buffer of size at least COSA_MAX_ID_STRING is expected */
+static inline int cosa_gettype(struct cosa_data *cosa, char *string)
+{
+	int l = strlen(cosa->type)+1;
+	copy_to_user_ret(string, cosa->type, l, -EFAULT);
+	return l;
+}
+
+static int cosa_ioctl_common(struct cosa_data *cosa,
+	struct channel_data *channel, unsigned int cmd, unsigned long arg)
+{
+	switch(cmd) {
+	case COSAIORSET:	/* Reset the device */
+		if (!suser())
+			return -EACCES;
+		return cosa_reset(cosa);
+	case COSAIOSTRT:	/* Start the firmware */
+		if (!suser())
+			return -EACCES;
+		return cosa_start(cosa, arg);
+	case COSAIODOWNLD:	/* Download the firmware */
+		if (!suser())
+			return -EACCES;
+		return cosa_download(cosa, (struct cosa_download *)arg);
+	case COSAIORMEM:
+		if (!suser())
+			return -EACCES;
+		return cosa_readmem(cosa, (struct cosa_download *)arg);
+	case COSAIORTYPE:
+		return cosa_gettype(cosa, (char *)arg);
+	case COSAIORIDSTR:
+		return cosa_getidstr(cosa, (char *)arg);
+/*
+ * These two are _very_ugly_hack_(tm). Don't even look at this.
+ * Implementing this saved me few reboots after some process segfaulted
+ * inside this module.
+ */
+#ifdef MODULE
+#if 0
+	case COSAIOMINC:
+		MOD_INC_USE_COUNT;
+		return 0;
+	case COSAIOMDEC:
+		MOD_DEC_USE_COUNT;
+		return 0;
+#endif
+#endif
+	case COSAIONRCARDS:
+		return nr_cards;
+	case COSAIONRCHANS:
+		return cosa->nchannels;
+	}
+	return -ENOIOCTLCMD;
+}
+
+static int cosa_sppp_ioctl(struct device *dev, struct ifreq *ifr,
+	int cmd)
+{
+	int rv;
+	struct channel_data *chan = (struct channel_data *)dev->priv;
+	rv = cosa_ioctl_common(chan->cosa, chan, cmd, (int)ifr->ifr_data);
+	if (rv == -ENOIOCTLCMD) {
+		return sppp_do_ioctl(dev, ifr, cmd);
+	}
+	return rv;
+}
+
+static int cosa_chardev_ioctl(struct inode *inode, struct file *file,
+	unsigned int cmd, unsigned long arg)
+{
+	struct channel_data *channel = (struct channel_data *)file->private_data;
+	struct cosa_data *cosa = channel->cosa;
+	return cosa_ioctl_common(cosa, channel, cmd, arg);
+}
+
+
+/*---------- HW layer interface ---------- */
+
+/*
+ * The higher layer can bind itself to the HW layer by setting the callbacks
+ * in the channel_data structure and by using these routines.
+ */
+static void cosa_enable_rx(struct channel_data *chan)
+{
+	struct cosa_data *cosa = chan->cosa;
+
+	if (!test_and_set_bit(chan->num, &cosa->rxbitmap))
+		put_driver_status(cosa);
+}
+
+static void cosa_disable_rx(struct channel_data *chan)
+{
+	struct cosa_data *cosa = chan->cosa;
+
+	if (test_and_clear_bit(chan->num, &cosa->rxbitmap))
+		put_driver_status(cosa);
+}
+
+/*
+ * FIXME: This routine probably should check for cosa_start_tx() called when
+ * the previous transmit is still unfinished. In this case the non-zero
+ * return value should indicate to the caller that the queuing(sp?) up
+ * the transmit has failed.
+ */
+static int cosa_start_tx(struct channel_data *chan, char *buf, int len)
+{
+	struct cosa_data *cosa = chan->cosa;
+	int flags;
+#ifdef DEBUG_DATA
+	int i;
+
+	printk(KERN_INFO "cosa%dc%d: starting tx(0x%x)", chan->cosa->num,
+		chan->num, len);
+	for (i=0; i<len; i++)
+		printk(" %02x", buf[i]&0xff);
+	printk("\n");
+#endif
+	spin_lock_irqsave(&cosa->lock, flags);
+	chan->txbuf = buf;
+	chan->txsize = len;
+	if (len > COSA_MTU)
+		chan->txsize = COSA_MTU;
+	spin_unlock_irqrestore(&cosa->lock, flags);
+
+	/* Tell the firmware we are ready */
+	set_bit(chan->num, &cosa->txbitmap);
+	put_driver_status(cosa);
+
+	return 0;
+}
+
+static void put_driver_status_common(struct cosa_data *cosa, int nolock)
+{
+	unsigned flags=0;
+	int status;
+
+	if (!nolock)
+		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->rxbitmap|cosa->txbitmap) {
+			cosa_putstatus(cosa, SR_RX_INT_ENA);
+#ifdef DEBUG_IO
+			debug_status_out(cosa, SR_RX_INT_ENA);
+#endif
+		} else {
+			cosa_putstatus(cosa, 0);
+#ifdef DEBUG_IO
+			debug_status_out(cosa, 0);
+#endif
+		}
+	}
+	if (!nolock)
+		spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+/*
+ * The "kickme" function: When the DMA times out, this is called to
+ * clean up the driver status.
+ * FIXME: Preliminary support, the interface is probably wrong.
+ */
+static void cosa_kick(struct cosa_data *cosa)
+{
+	unsigned flags, flags1;
+
+	printk(KERN_INFO "%s: DMA timeout - restarting.\n", cosa->name);
+
+	spin_lock_irqsave(&cosa->lock, flags);
+	cosa->rxtx = 0;
+
+	flags1 = claim_dma_lock();
+	disable_dma(cosa->dma);
+	clear_dma_ff(cosa->dma);
+	release_dma_lock(flags1);
+
+	/* FIXME: Anything else? */
+	put_driver_status_nolock(cosa);
+	spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+/*
+ * Check if the whole buffer is DMA-able. It means it is below the 16M of
+ * physical memory and doesn't span the 64k boundary. For now it seems
+ * SKB's never do this, but we'll check this anyway.
+ */
+static int cosa_dma_able(struct channel_data *chan, char *buf, int len)
+{
+	static int count = 0;
+	unsigned long b = (unsigned long)buf;
+	if (b+len >= MAX_DMA_ADDRESS)
+		return 0;
+	if ((b^ (b+len)) & 0x10000) {
+		if (count++ < 5)
+			printk(KERN_INFO "%s: packet spanning a 64k boundary\n",
+				chan->name);
+		return 0;
+	}
+	return 1;
+}
+
+
+/* ---------- The SRP/COSA ROM monitor functions ---------- */
+
+/*
+ * Downloading SRP microcode: say "w" to SRP monitor, it answers by "w=",
+ * drivers need to say 4-digit hex number meaning start address of the microcode
+ * separated by a single space. Monitor replies by saying " =". Now driver
+ * has to write 4-digit hex number meaning the last byte address ended
+ * by a single space. Monitor has to reply with a space. Now the download
+ * begins. After the download monitor replies with "\r\n." (CR LF dot).
+ */
+static int download(struct cosa_data *cosa, char *microcode, int length, int address)
+{
+	int i;
+
+	if (put_wait_data(cosa, 'w') == -1) return -1;
+	if ((i=get_wait_data(cosa)) != 'w') { printk("dnld: 0x%04x\n",i); return -2;}
+	if (get_wait_data(cosa) != '=') return -3;
+
+	if (puthexnumber(cosa, address) < 0) return -4;
+	if (put_wait_data(cosa, ' ') == -1) return -10;
+	if (get_wait_data(cosa) != ' ') return -11;
+	if (get_wait_data(cosa) != '=') return -12;
+
+	if (puthexnumber(cosa, address+length-1) < 0) return -13;
+	if (put_wait_data(cosa, ' ') == -1) return -18;
+	if (get_wait_data(cosa) != ' ') return -19;
+
+	while (length--) {
+		char c;
+#ifndef SRP_DOWNLOAD_AT_BOOT
+		get_user_ret(c,microcode, -23);
+#else
+		c = *microcode;
+#endif
+		if (put_wait_data(cosa, c) == -1)
+			return -20;
+		microcode++;
+	}
+
+	if (get_wait_data(cosa) != '\r') return -21;
+	if (get_wait_data(cosa) != '\n') return -22;
+	if (get_wait_data(cosa) != '.') return -23;
+#if 0
+	printk(KERN_DEBUG "cosa%d: download completed.\n", cosa->num);
+#endif
+	return 0;
+}
+
+
+/*
+ * Starting microcode is done via the "g" command of the SRP monitor.
+ * The chat should be the following: "g" "g=" "<addr><CR>"
+ * "<CR><CR><LF><CR><LF>".
+ */
+static int startmicrocode(struct cosa_data *cosa, int address)
+{
+	if (put_wait_data(cosa, 'g') == -1) return -1;
+	if (get_wait_data(cosa) != 'g') return -2;
+	if (get_wait_data(cosa) != '=') return -3;
+
+	if (puthexnumber(cosa, address) < 0) return -4;
+	if (put_wait_data(cosa, '\r') == -1) return -5;
+	
+	if (get_wait_data(cosa) != '\r') return -6;
+	if (get_wait_data(cosa) != '\r') return -7;
+	if (get_wait_data(cosa) != '\n') return -8;
+	if (get_wait_data(cosa) != '\r') return -9;
+	if (get_wait_data(cosa) != '\n') return -10;
+#if 0
+	printk(KERN_DEBUG "cosa%d: microcode started\n", cosa->num);
+#endif
+	return 0;
+}
+
+/*
+ * Reading memory is done via the "r" command of the SRP monitor.
+ * The chat is the following "r" "r=" "<addr> " " =" "<last_byte> " " "
+ * Then driver can read the data and the conversation is finished
+ * by SRP monitor sending "<CR><LF>." (dot at the end).
+ *
+ * This routine is not needed during the normal operation and serves
+ * for debugging purposes only.
+ */
+static int readmem(struct cosa_data *cosa, char *microcode, int length, int address)
+{
+	if (put_wait_data(cosa, 'r') == -1) return -1;
+	if ((get_wait_data(cosa)) != 'r') return -2;
+	if ((get_wait_data(cosa)) != '=') return -3;
+
+	if (puthexnumber(cosa, address) < 0) return -4;
+	if (put_wait_data(cosa, ' ') == -1) return -5;
+	if (get_wait_data(cosa) != ' ') return -6;
+	if (get_wait_data(cosa) != '=') return -7;
+
+	if (puthexnumber(cosa, address+length-1) < 0) return -8;
+	if (put_wait_data(cosa, ' ') == -1) return -9;
+	if (get_wait_data(cosa) != ' ') return -10;
+
+	while (length--) {
+		char c;
+		int i;
+		if ((i=get_wait_data(cosa)) == -1) {
+			printk (KERN_INFO "cosa: 0x%04x bytes remaining\n",
+				length);
+			return -11;
+		}
+		c=i;
+#if 1
+		put_user_ret(c,microcode, -23);
+#else
+		*microcode = c;
+#endif
+		microcode++;
+	}
+
+	if (get_wait_data(cosa) != '\r') return -21;
+	if (get_wait_data(cosa) != '\n') return -22;
+	if (get_wait_data(cosa) != '.') return -23;
+#if 0
+	printk(KERN_DEBUG "cosa%d: readmem completed.\n", cosa->num);
+#endif
+	return 0;
+}
+
+/*
+ * This function resets the device and reads the initial prompt
+ * of the device's ROM monitor.
+ */
+static int cosa_reset_and_read_id(struct cosa_data *cosa, char *idstring)
+{
+	int i=0, id=0, prev=0, curr=0;
+
+	/* Reset the card ... */
+	cosa_putstatus(cosa, 0);
+	cosa_getdata8(cosa);
+	cosa_putstatus(cosa, SR_RST);
+#ifdef MODULE
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(HZ/2);
+	current->state = TASK_RUNNING;
+#else
+	udelay(5*100000);
+#endif
+	/* Disable all IRQs from the card */
+	cosa_putstatus(cosa, 0);
+
+	/*
+	 * Try to read the ID string. The card then prints out the
+	 * identification string ended by the "\n\x2e".
+	 *
+	 * The following loop is indexed through i (instead of id)
+	 * to avoid looping forever when for any reason
+	 * the port returns '\r', '\n' or '\x2e' permanently.
+	 */
+	for (i=0; i<COSA_MAX_ID_STRING-1; i++, prev=curr) {
+		if ((curr = get_wait_data(cosa)) == -1) {
+			return -1;
+		}
+		curr &= 0xff;
+		if (curr != '\r' && curr != '\n' && curr != 0x2e)
+			idstring[id++] = curr;
+		if (curr == 0x2e && prev == '\n')
+			break;
+	}
+	/* Perhaps we should fail when i==COSA_MAX_ID_STRING-1 ? */
+	idstring[id] = '\0';
+	return id;
+}
+
+
+/* ---------- Auxiliary routines for COSA/SRP monitor ---------- */
+
+/*
+ * This routine gets the data byte from the card waiting for the SR_RX_RDY
+ * bit to be set in a loop. It should be used in the exceptional cases
+ * only (for example when resetting the card or downloading the firmware.
+ */
+static int get_wait_data(struct cosa_data *cosa)
+{
+	int retries = 1000;
+
+	while (--retries) {
+		/* read data and return them */
+		if (cosa_getstatus(cosa) & SR_RX_RDY) {
+			short r;
+			r = cosa_getdata8(cosa);
+#if 0
+			printk(KERN_INFO "cosa: get_wait_data returning after %d retries\n", 999-retries);
+#endif
+			return r;
+		}
+		/* sleep if not ready to read */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+		current->state = TASK_RUNNING;
+	}
+	printk(KERN_INFO "cosa: timeout in get_wait_data (status 0x%x)\n",
+		cosa_getstatus(cosa));
+	return -1;
+}
+
+/*
+ * This routine puts the data byte to the card waiting for the SR_TX_RDY
+ * bit to be set in a loop. It should be used in the exceptional cases
+ * only (for example when resetting the card or downloading the firmware).
+ */
+static int put_wait_data(struct cosa_data *cosa, int data)
+{
+	int retries = 1000;
+	while (--retries) {
+		/* read data and return them */
+		if (cosa_getstatus(cosa) & SR_TX_RDY) {
+			cosa_putdata8(cosa, data);
+#if 0
+			printk(KERN_INFO "Putdata: %d retries\n", 999-retries);
+#endif
+			return 0;
+		}
+#if 0
+		/* sleep if not ready to read */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(1);
+		current->state = TASK_RUNNING;
+#endif
+	}
+	printk(KERN_INFO "cosa%d: timeout in put_wait_data (status 0x%x)\n",
+		cosa->num, cosa_getstatus(cosa));
+	return -1;
+}
+	
+/* 
+ * The following routine puts the hexadecimal number into the SRP monitor
+ * and verifies the proper echo of the sent bytes. Returns 0 on success,
+ * negative number on failure (-1,-3,-5,-7) means that put_wait_data() failed,
+ * (-2,-4,-6,-8) means that reading echo failed.
+ */
+static int puthexnumber(struct cosa_data *cosa, int number)
+{
+	char temp[5];
+	int i;
+
+	/* Well, I should probably replace this by something faster. */
+	sprintf(temp, "%04X", number);
+	for (i=0; i<4; i++) {
+		if (put_wait_data(cosa, temp[i]) == -1) {
+			printk(KERN_NOTICE "cosa%d: puthexnumber failed to write byte %d\n",
+				cosa->num, i);
+			return -1-2*i;
+		}
+		if (get_wait_data(cosa) != temp[i]) {
+			printk(KERN_NOTICE "cosa%d: puthexhumber failed to read echo of byte %d\n",
+				cosa->num, i);
+			return -2-2*i;
+		}
+	}
+	return 0;
+}
+
+
+/* ---------- Interrupt routines ---------- */
+
+/*
+ * There are three types of interrupt:
+ * At the beginning of transmit - this handled is in tx_interrupt(),
+ * at the beginning of receive - it is in rx_interrupt() and
+ * at the end of transmit/receive - it is the eot_interrupt() function.
+ * These functions are multiplexed by cosa_interrupt() according to the
+ * 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.
+ */
+static inline void tx_interrupt(struct cosa_data *cosa, int status)
+{
+	unsigned long flags, flags1;
+#ifdef DEBUG_IRQS
+	printk(KERN_INFO "cosa%d: SR_DOWN_REQUEST status=0x%04x\n",
+		cosa->num, status);
+#endif
+	spin_lock_irqsave(&cosa->lock, flags);
+	set_bit(TXBIT, &cosa->rxtx);
+	/*
+	 * Using a round-robin algorithm select a first channel that has
+	 * data ready for transmit.
+	 */
+	if (!test_bit(IRQBIT, &cosa->rxtx)) {
+		do {
+			cosa->txchan++;
+			if (cosa->txchan >= cosa->nchannels)
+				cosa->txchan = 0;
+		} while(!(cosa->txbitmap & (1<<cosa->txchan)));
+		cosa->txsize = cosa->chan[cosa->txchan].txsize;
+		if (cosa_dma_able(cosa->chan+cosa->txchan,
+			cosa->chan[cosa->txchan].txbuf, cosa->txsize)) {
+			cosa->txbuf = cosa->chan[cosa->txchan].txbuf;
+		} else {
+			memcpy(cosa->bouncebuf, cosa->chan[cosa->txchan].txbuf,
+				cosa->txsize);
+			cosa->txbuf = cosa->bouncebuf;
+		}
+	}
+
+	if (is_8bit(cosa)) {
+		if (!test_bit(IRQBIT, &cosa->rxtx)) {
+			cosa_putdata8(cosa, ((cosa->txchan << 5) & 0xe0)|
+				((cosa->txsize >> 8) & 0x1f));
+			cosa_putstatus(cosa, SR_TX_INT_ENA);
+#ifdef DEBUG_IO
+			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);
+#endif
+			set_bit(IRQBIT, &cosa->rxtx);
+			spin_unlock_irqrestore(&cosa->lock, flags);
+			return;
+		} else {
+			clear_bit(IRQBIT, &cosa->rxtx);
+			cosa_putstatus(cosa, 0);
+			cosa_putdata8(cosa, cosa->txsize&0xff);
+#ifdef DEBUG_IO
+			debug_status_out(cosa, 0);
+			debug_data_out(cosa, cosa->txsize&0xff);
+#endif
+		}
+	} else {
+		cosa_putdata16(cosa, ((cosa->txchan<<13) & 0xe000)
+			| (cosa->txsize & 0x1fff));
+		cosa_getdata16(cosa);
+#ifdef DEBUG_IO
+		debug_status_out(cosa, ((cosa->txchan<<13) & 0xe000)
+                        | (cosa->txsize & 0x1fff));
+		debug_data_in(cosa, cosa_getdata16(cosa));
+#else
+		cosa_getdata16(cosa);
+#endif
+	}
+
+	/* 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);
+#endif
+	spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static inline void rx_interrupt(struct cosa_data *cosa, int status)
+{
+	unsigned long flags;
+#ifdef DEBUG_IRQS
+	printk(KERN_INFO "cosa%d: SR_UP_REQUEST\n", cosa->num);
+#endif
+
+	spin_lock_irqsave(&cosa->lock, flags);
+	set_bit(RXBIT, &cosa->rxtx);
+
+	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
+			printk(KERN_INFO "cosa%d: receive rxsize = (0x%04x).\n",
+				cosa->num, cosa->rxsize);
+#endif
+		}
+	} 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",
+			cosa->num, cosa->rxsize);
+#endif
+	}
+	if (((cosa->rxsize & 0xe000) >> 13) >= cosa->nchannels) {
+		printk(KERN_WARNING "%s: rx for unknown channel (0x%04x)\n",
+			cosa->name, cosa->rxsize);
+		spin_unlock_irqrestore(&cosa->lock, flags);
+		goto reject;
+	}
+	cosa->rxchan = cosa->chan + ((cosa->rxsize & 0xe000) >> 13);
+	cosa->rxsize &= 0x1fff;
+	spin_unlock_irqrestore(&cosa->lock, flags);
+
+	cosa->rxbuf = NULL;
+	if (cosa->rxchan->setup_rx)
+		cosa->rxbuf = cosa->rxchan->setup_rx(cosa->rxchan, cosa->rxsize);
+
+	if (!cosa->rxbuf) {
+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;
+	}
+
+	/* start the DMA */
+	flags = claim_dma_lock();
+	disable_dma(cosa->dma);
+	clear_dma_ff(cosa->dma);
+	set_dma_mode(cosa->dma, DMA_MODE_READ);
+	if (cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize & 0x1fff)) {
+		set_dma_addr(cosa->dma, virt_to_bus(cosa->rxbuf));
+	} else {
+		set_dma_addr(cosa->dma, virt_to_bus(cosa->bouncebuf));
+	}
+	set_dma_count(cosa->dma, (cosa->rxsize&0x1fff));
+	enable_dma(cosa->dma);
+	release_dma_lock(flags);
+	spin_lock_irqsave(&cosa->lock, flags);
+	cosa_putstatus(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+#ifdef DEBUG_IO
+	debug_status_out(cosa, SR_RX_DMA_ENA|SR_USR_INT_ENA);
+#endif
+	spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void inline eot_interrupt(struct cosa_data *cosa, int status)
+{
+	unsigned long flags, flags1;
+	spin_lock_irqsave(&cosa->lock, flags);
+	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);
+	} else if (test_bit(RXBIT, &cosa->rxtx)) {
+#ifdef DEBUG_DATA
+	{
+		int i;
+		printk(KERN_INFO "cosa%dc%d: done rx(0x%x)", cosa->num, 
+			cosa->rxchan->num, cosa->rxsize);
+		for (i=0; i<cosa->rxsize; i++)
+			printk (" %02x", cosa->rxbuf[i]&0xff);
+		printk("\n");
+	}
+#endif
+		if (!cosa_dma_able(cosa->rxchan, cosa->rxbuf, cosa->rxsize))
+			memcpy(cosa->rxbuf, cosa->bouncebuf, cosa->rxsize);
+		if (cosa->rxchan->rx_done)
+			if (cosa->rxchan->rx_done(cosa->rxchan))
+				clear_bit(cosa->rxchan->num, &cosa->rxbitmap);
+	} else {
+		printk(KERN_NOTICE "cosa%d: unexpected EOT interrupt\n",
+			cosa->num);
+	}
+	/*
+	 * Clear the RXBIT, TXBIT and IRQBIT (the latest should be
+	 * cleared anyway).
+	 */
+	flags1 = claim_dma_lock();
+	disable_dma(cosa->dma);
+	clear_dma_ff(cosa->dma);
+	release_dma_lock(flags1);
+	cosa->rxtx = 0;
+	put_driver_status_nolock(cosa);
+	spin_unlock_irqrestore(&cosa->lock, flags);
+}
+
+static void cosa_interrupt(int irq, void *cosa_, struct pt_regs *regs)
+{
+	int status;
+	int count = 0;
+	struct cosa_data *cosa = cosa_;
+again:
+	status = cosa_getstatus(cosa);
+#ifdef DEBUG_IRQS
+	printk(KERN_INFO "cosa%d: got IRQ, status 0x%02x\n", cosa->num,
+		status & 0xff);
+#endif
+#ifdef DEBUG_IO
+	debug_status_in(cosa, status);
+#endif
+	switch (status & SR_CMD_FROM_SRP_MASK) {
+	case SR_DOWN_REQUEST:
+		tx_interrupt(cosa, status);
+		break;
+	case SR_UP_REQUEST:
+		rx_interrupt(cosa, status);
+		break;
+	case SR_END_OF_TRANSFER:
+		eot_interrupt(cosa, status);
+		break;
+	default:
+		/* We may be too fast for SRP. Try to wait a bit more. */
+		if (count++ < 100) {
+			udelay(100);
+			goto again;
+		}
+		printk(KERN_INFO "cosa%d: unknown status 0x%02x in IRQ after %d retries\n",
+			cosa->num, status & 0xff, count);
+	}
+#ifdef DEBUG_IRQS
+	if (count)
+		printk(KERN_INFO "%s: %d-times got unknown status in IRQ\n",
+			cosa->name, count);
+	else
+		printk(KERN_INFO "%s: returning from IRQ\n", cosa->name);
+#endif
+}
+
+
+/* ---------- I/O debugging routines ---------- */
+/*
+ * These routines can be used to monitor COSA/SRP I/O and to printk()
+ * the data being transfered on the data and status I/O port in a
+ * readable way.
+ */
+
+#ifdef DEBUG_IO
+static void debug_status_in(struct cosa_data *cosa, int status)
+{
+	char *s;
+	switch(status & SR_CMD_FROM_SRP_MASK) {
+	case SR_UP_REQUEST:
+		s = "RX_REQ";
+		break;
+	case SR_DOWN_REQUEST:
+		s = "TX_REQ";
+		break;
+	case SR_END_OF_TRANSFER:
+		s = "ET_REQ";
+		break;
+	default:
+		s = "NO_REQ";
+		break;
+	}
+	printk(KERN_INFO "%s: IO: status -> 0x%02x (%s%s%s%s)\n",
+		cosa->name,
+		status,
+		status & SR_USR_RQ ? "USR_RQ|":"",
+		status & SR_TX_RDY ? "TX_RDY|":"",
+		status & SR_RX_RDY ? "RX_RDY|":"",
+		s);
+}
+
+static void debug_status_out(struct cosa_data *cosa, int status)
+{
+	printk(KERN_INFO "%s: IO: status <- 0x%02x (%s%s%s%s%s%s)\n",
+		cosa->name,
+		status,
+		status & SR_RX_DMA_ENA  ? "RXDMA|":"!rxdma|",
+		status & SR_TX_DMA_ENA  ? "TXDMA|":"!txdma|",
+		status & SR_RST         ? "RESET|":"",
+		status & SR_USR_INT_ENA ? "USRINT|":"!usrint|",
+		status & SR_TX_INT_ENA  ? "TXINT|":"!txint|",
+		status & SR_RX_INT_ENA  ? "RXINT":"!rxint");
+}
+
+static void debug_data_in(struct cosa_data *cosa, int data)
+{
+	printk(KERN_INFO "%s: IO: data -> 0x%04x\n", cosa->name, data);
+}
+
+static void debug_data_out(struct cosa_data *cosa, int data)
+{
+	printk(KERN_INFO "%s: IO: data <- 0x%04x\n", cosa->name, data);
+}
+
+static void debug_data_cmd(struct cosa_data *cosa, int data)
+{
+	printk(KERN_INFO "%s: IO: data <- 0x%04x (%s|%s)\n",
+		cosa->name, data,
+		data & SR_RDY_RCV ? "RX_RDY" : "!rx_rdy",
+		data & SR_RDY_SND ? "TX_RDY" : "!tx_rdy");
+}
+#endif
+
+/* EOF -- this file has not been truncated */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/cosa.h linux/drivers/net/cosa.h
--- v2.1.131/linux/drivers/net/cosa.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/cosa.h	Thu Dec 17 09:04:49 1998
@@ -0,0 +1,102 @@
+/* $Id: cosa.h,v 1.8 1998/11/09 03:54:49 kas Exp $ */
+
+/*
+ *  Copyright (C) 1995-1997  Jan "Yenya" Kasprzak <kas@fi.muni.cz>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef COSA_H__
+#define COSA_H__
+
+#include <linux/ioctl.h>
+
+#ifdef __KERNEL__
+/* status register - output bits */
+#define SR_RX_DMA_ENA   0x04    /* receiver DMA enable bit */
+#define SR_TX_DMA_ENA   0x08    /* transmitter DMA enable bit */
+#define SR_RST          0x10    /* SRP reset */
+#define SR_USR_INT_ENA  0x20    /* user interrupt enable bit */
+#define SR_TX_INT_ENA   0x40    /* transmitter interrupt enable bit */
+#define SR_RX_INT_ENA   0x80    /* receiver interrupt enable bit */
+
+/* status register - input bits */
+#define SR_USR_RQ       0x20    /* user interupt request pending */
+#define SR_TX_RDY       0x40    /* transmitter empty (ready) */
+#define SR_RX_RDY       0x80    /* receiver data ready */
+
+#define SR_UP_REQUEST   0x02    /* request from SRP to transfer data
+                                   up to PC */
+#define SR_DOWN_REQUEST 0x01    /* SRP is able to transfer data down
+                                   from PC to SRP */
+#define SR_END_OF_TRANSFER      0x03    /* SRP signalize end of
+                                           transfer (up or down) */
+
+#define SR_CMD_FROM_SRP_MASK    0x03    /* mask to get SRP command */
+
+/* bits in driver status byte definitions : */
+#define SR_RDY_RCV      0x01    /* ready to receive packet */
+#define SR_RDY_SND      0x02    /* ready to send packet */
+#define SR_CMD_PND      0x04    /* command pending */ /* not currently used */
+
+/* ???? */
+#define SR_PKT_UP       0x01    /* transfer of packet up in progress */
+#define SR_PKT_DOWN     0x02    /* transfer of packet down in progress */
+
+#endif /* __KERNEL__ */
+
+#define SR_LOAD_ADDR    0x4400  /* SRP microcode load address */
+#define SR_START_ADDR   0x4400  /* SRP microcode start address */
+
+#define COSA_LOAD_ADDR    0x400  /* SRP microcode load address */
+
+
+/* ioctls */
+struct cosa_download {
+	int addr, len;
+	char *code;
+};
+
+/* Reset the device */
+#define COSAIORSET	_IO('C',0xf0)
+
+/* Start microcode at given address */
+#define COSAIOSTRT	_IOW('C',0xf1,sizeof(int))
+
+/* Read the block from the device memory */
+#define COSAIORMEM	_IOR('C',0xf2,sizeof(struct cosa_download *))
+
+/* Write the block to the device memory (i.e. download the microcode) */
+#define COSAIODOWNLD	_IOW('C',0xf2,sizeof(struct cosa_download *))
+
+/* Read the device type (one of "srp", "cosa", and "cosa8" for now) */
+#define COSAIORTYPE	_IOR('C',0xf3,sizeof(char *))
+
+/* Read the device identification string */
+#define COSAIORIDSTR	_IOR('C',0xf4,sizeof(char *))
+/* Maximum length of the identification string. */
+#define COSA_MAX_ID_STRING 128
+
+/* Increment/decrement the module usage count :-) */
+/* #define COSAIOMINC	_IO('C',0xf5) */
+/* #define COSAIOMDEC	_IO('C',0xf6) */
+
+/* Get the total number of cards installed */
+#define COSAIONRCARDS	_IO('C',0xf7)
+
+/* Get the number of channels on this card */
+#define COSAIONRCHANS	_IO('C',0xf8)
+
+#endif /* !COSA_H__ */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/daynaport.c linux/drivers/net/daynaport.c
--- v2.1.131/linux/drivers/net/daynaport.c	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/daynaport.c	Thu Dec 17 09:04:49 1998
@@ -340,13 +340,13 @@
 {
 	static unsigned version_printed = 0;
 
-	static int fwrd4_offsets[16]={
+	static u32 fwrd4_offsets[16]={
 		0,      4,      8,      12,
 		16,     20,     24,     28,
 		32,     36,     40,     44,
 		48,     52,     56,     60
 	};
-	static int back4_offsets[16]={
+	static u32 back4_offsets[16]={
 		60,     56,     52,     48,
 		44,     40,     36,     32,
 		28,     24,     20,     16,
diff -u --recursive --new-file v2.1.131/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
--- v2.1.131/linux/drivers/net/e2100.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/net/e2100.c	Wed Dec 16 13:35:49 1998
@@ -449,7 +449,6 @@
 			void *priv = dev->priv;
 			/* NB: e21_close() handles free_irq */
 			release_region(dev->base_addr, E21_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.1.131/linux/drivers/net/epic100.c	Fri May  8 23:14:48 1998
+++ linux/drivers/net/epic100.c	Fri Dec 18 08:06:39 1998
@@ -1,25 +1,24 @@
-/* epic100.c: A SMC 83c170 EPIC/100 fast ethernet driver for Linux. */
+/* epic100.c: A SMC 83c170 EPIC/100 Fast Ethernet driver for Linux. */
 /*
-   NOTICE: THIS IS THE ALPHA TEST VERSION!
-	Written 1997 by Donald Becker.
+	Written/copyright 1997-1998 by Donald Becker.
 
 	This software may be used and distributed according to the terms
 	of the GNU Public License, incorporated herein by reference.
-    All other rights reserved.
+	All other rights reserved.
 
-	This driver is for the SMC EtherPower II 9432 PCI ethernet adapter based on
-	the SMC83c170.
+	This driver is for the SMC83c170/175 "EPIC" series, as used on the
+	SMC EtherPower II 9432 PCI adapter, and several CardBus cards.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
-	Center of Excellence in Space Data and Information Sciences
+	USRA Center of Excellence in Space Data and Information Sciences
 	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
-	Support and updates available at
+	Information and updates available at
 	http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html
 */
 
 static const char *version =
-"epic100.c:v0.10 10/14/97 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
+"epic100.c:v1.04 8/23/98 Donald Becker http://cesdis.gsfc.nasa.gov/linux/drivers/epic100.html\n";
 
 /* A few user-configurable values. */
 
@@ -32,7 +31,7 @@
 
 /* Set the copy breakpoint for the copy-only-tiny-frames scheme.
    Setting to > 1518 effectively disables this feature. */
-static const int rx_copybreak = 200;
+static int rx_copybreak = 200;
 
 /* Maximum events (Rx packets, etc.) to handle at each interrupt. */
 static int max_interrupt_work = 10;
@@ -44,16 +43,15 @@
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
 /* Bytes transferred to chip before transmission starts. */
-#define TX_FIFO_THRESH 128		/* Rounded down to 4 byte units. */
+#define TX_FIFO_THRESH 256		/* Rounded down to 4 byte units. */
 #define RX_FIFO_THRESH 1		/* 0-3, 0==32, 64,96, or 3==128 bytes  */
 
-#include <linux/config.h>
+#include <linux/version.h>		/* Evil, but neccessary */
 #ifdef MODULE
 #ifdef MODVERSIONS
 #include <linux/modversions.h>
 #endif
 #include <linux/module.h>
-#include <linux/version.h>
 #else
 #define MOD_INC_USE_COUNT
 #define MOD_DEC_USE_COUNT
@@ -69,6 +67,13 @@
 #include <linux/malloc.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
+#if LINUX_VERSION_CODE >= 0x20155
+#define PCI_SUPPORT_VER2
+#else
+#include <linux/bios32.h>
+#endif
+#include <linux/delay.h>
+
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -80,70 +85,39 @@
 
 /* Kernel compatibility defines, common to David Hind's PCMCIA package.
    This is only in the support-all-kernels source code. */
-#include <linux/version.h>		/* Evil, but neccessary */
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10300
-#define RUN_AT(x) (x)			/* What to put in timer->expires.  */
-#define DEV_ALLOC_SKB(len) alloc_skb(len, GFP_ATOMIC)
-#define virt_to_bus(addr)  ((unsigned long)addr)
-#define bus_to_virt(addr) ((void*)addr)
-
-#else  /* 1.3.0 and later */
-#define RUN_AT(x) (jiffies + (x))
-#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+#if ! defined (LINUX_VERSION_CODE) || LINUX_VERSION_CODE < 0x20000
+#warning This driver version is only for kernel versions 2.0.0 and later.
 #endif
 
-#if defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE < 0x10338
-#ifdef MODULE
-#if !defined(CONFIG_MODVERSIONS) && !defined(__NO_VERSION__)
-char kernel_version[] = UTS_RELEASE;
-#endif
-#else
-#undef MOD_INC_USE_COUNT
-#define MOD_INC_USE_COUNT
-#undef MOD_DEC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-#endif /* 1.3.38 */
-
-#if (LINUX_VERSION_CODE >= 0x10344)
-#define NEW_MULTICAST
-#include <linux/delay.h>
-#endif
-
-#ifdef SA_SHIRQ
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum, dev)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n, instance)
-#define IRQ(irq, dev_id, pt_regs) (irq, dev_id, pt_regs)
-#else
-#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
-#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
-#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
-#endif
+#define RUN_AT(x) (jiffies + (x))
 
-#if (LINUX_VERSION_CODE < 0x20123)
-#define test_and_set_bit(val, addr) set_bit(val, addr)
-#include <linux/bios32.h>
-#else
-#ifdef MODULE
+#if defined(MODULE) && (LINUX_VERSION_CODE >= 0x20115)
 MODULE_AUTHOR("Donald Becker <becker@cesdis.gsfc.nasa.gov>");
-MODULE_DESCRIPTION("SMC 82c170 EPIC series Ethernet driver");
+MODULE_DESCRIPTION("SMC 83c170 EPIC series Ethernet driver");
 MODULE_PARM(debug, "i");
 MODULE_PARM(options, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(full_duplex, "1-" __MODULE_STRING(8) "i");
 MODULE_PARM(rx_copybreak, "i");
 MODULE_PARM(max_interrupt_work, "i");
 #endif
+#if LINUX_VERSION_CODE < 0x20123
+#define test_and_set_bit(val, addr) set_bit(val, addr)
+#endif
+#if LINUX_VERSION_CODE <= 0x20139
+#define	net_device_stats enet_statistics
+#define NETSTATS_VER2
+#endif
+#if LINUX_VERSION_CODE < 0x20159
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb, FREE_WRITE);
+#else  /* Grrr, unneeded incompatible change. */
+#define DEV_FREE_SKB(skb) dev_kfree_skb(skb);
 #endif
 
 /* The I/O extent. */
 #define EPIC_TOTAL_SIZE 0x100
 
-#ifdef HAVE_DEVLIST
-struct netdev_entry epic100_drv =
-{"Epic100", epic100_pci_probe, EPIC_TOTAL_SIZE, NULL};
-#endif
-
+#define epic_debug debug
 static int epic_debug = 1;
 
 /*
@@ -152,7 +126,7 @@
 I. Board Compatibility
 
 This device driver is designed for the SMC "EPCI/100", the SMC
-single-chip ethernet controllers for PCI.  This chip is used on
+single-chip Ethernet controllers for PCI.  This chip is used on
 the SMC EtherPower II boards.
 
 
@@ -178,17 +152,34 @@
 
 */
 
-#ifndef PCI_VENDOR_ID_SMC
-#define PCI_VENDOR_ID_SMC			0x10B8
-#endif
-#ifndef PCI_DEVICE_ID_SMC_EPIC100
-#define PCI_DEVICE_ID_SMC_EPIC100	0x0005
-#endif
-
 /* The rest of these values should never change. */
+
+static struct device *epic_probe1(int pci_bus, int pci_devfn,
+								  struct device *dev, long ioaddr, int irq,
+								  int chip_id, int card_idx);
+
+enum pci_flags_bit {
+	PCI_USES_IO=1, PCI_USES_MEM=2, PCI_USES_MASTER=4,
+	PCI_ADDR0=0x10<<0, PCI_ADDR1=0x10<<1, PCI_ADDR2=0x10<<2, PCI_ADDR3=0x10<<3,
+};
+struct chip_info {
+	const char *name;
+	u16	vendor_id, device_id, device_id_mask, pci_flags;
+	int io_size, min_latency;
+	struct device *(*probe1)(int pci_bus, int pci_devfn, struct device *dev,
+							 long ioaddr, int irq, int chip_idx, int fnd_cnt);
+} chip_tbl[] = {
+	{"SMSC EPIC/100 83c170", 0x10B8, 0x0005, 0x7fff,
+	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+	{"SMSC EPIC/C 83c175", 0x10B8, 0x0006, 0x7fff,
+	 PCI_USES_IO|PCI_USES_MASTER|PCI_ADDR0, EPIC_TOTAL_SIZE, 32, epic_probe1},
+	{0,},
+};
+
 /* Offsets to registers, using the (ugh) SMC names. */
 enum epic_registers {
   COMMAND=0, INTSTAT=4, INTMASK=8, GENCTL=0x0C, NVCTL=0x10, EECTL=0x14,
+  PCIBurstCnt=0x18,
   TEST1=0x1C, CRCCNT=0x20, ALICNT=0x24, MPCNT=0x28,	/* Rx error counters. */
   MIICtrl=0x30, MIIData=0x34, MIICfg=0x38,
   LAN0=64,						/* MAC address. */
@@ -199,8 +190,9 @@
 
 /* Interrupt register bits, using my own meaningful names. */
 enum IntrStatus {
-  TxIdle=0x40000, RxIdle=0x20000,
-  CntFull=0x0200, TxUnderrun=0x0100,
+  TxIdle=0x40000, RxIdle=0x20000, IntrSummary=0x010000,
+  PCIBusErr170=0x7000, PCIBusErr175=0x1000, PhyEvent175=0x8000,
+  RxStarted=0x0800, RxEarlyWarn=0x0400, CntFull=0x0200, TxUnderrun=0x0100,
   TxEmpty=0x0080, TxDone=0x0020, RxError=0x0010,
   RxOverflow=0x0008, RxFull=0x0004, RxHeader=0x0002, RxDone=0x0001,
 };
@@ -213,7 +205,7 @@
 	u32 bufaddr;
 	u16 buflength;
 	u16 control;
-    u32 next;
+	u32 next;
 };
 
 struct epic_rx_desc {
@@ -221,29 +213,36 @@
 	u16 rxlength;
 	u32 bufaddr;
 	u32 buflength;
-    u32 next;
+	u32 next;
 };
 
 struct epic_private {
 	char devname[8];			/* Used only for kernel debugging. */
 	const char *product_name;
 	struct device *next_module;
+
+	/* Rx and Rx rings here so that they remain paragraph aligned. */
 	struct epic_rx_desc rx_ring[RX_RING_SIZE];
 	struct epic_tx_desc tx_ring[TX_RING_SIZE];
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
 	/* The addresses of receive-in-place skbuffs. */
 	struct sk_buff* rx_skbuff[RX_RING_SIZE];
-	int chip_id;
-	int revision;
-	struct enet_statistics stats;
-	struct timer_list timer;	/* Media selection timer. */
+
+	/* Ring pointers. */
 	unsigned int cur_rx, cur_tx;		/* The next free ring entry */
 	unsigned int dirty_rx, dirty_tx;	/* The ring entries to be free()ed. */
+
+	u8 pci_bus, pci_dev_fn;				/* PCI bus location. */
+	u16 chip_id;
+
+	struct net_device_stats stats;
+	struct timer_list timer;			/* Media selection timer. */
 	unsigned char mc_filter[8];
 	signed char phys[4];				/* MII device addresses. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
-	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
+	unsigned int full_duplex:1;			/* Current duplex setting. */
+	unsigned int force_fd:1;			/* Full-duplex operation requested. */
 	unsigned int default_port:4;		/* Last dev->if_port value. */
 	unsigned int media2:4;				/* Secondary monitored media port. */
 	unsigned int medialock:1;			/* Don't sense media type. */
@@ -251,162 +250,174 @@
 	int pad0, pad1;						/* Used for 8-byte alignment */
 };
 
-static int full_duplex[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#ifdef MODULE
 /* Used to pass the full-duplex flag, etc. */
-static int options[] = {-1, -1, -1, -1, -1, -1, -1, -1};
-#endif
+#define MAX_UNITS 8
+static int full_duplex[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
+static int options[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
-static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
-                                 int chip_id, int options, int card_idx);
 static int epic_open(struct device *dev);
-static int read_eeprom(int ioaddr, int location);
-static int mii_read(int ioaddr, int phy_id, int location);
+static int read_eeprom(long ioaddr, int location);
+static int mdio_read(long ioaddr, int phy_id, int location);
+static void mdio_write(long ioaddr, int phy_id, int location, int value);
+static void epic_restart(struct device *dev);
 static void epic_timer(unsigned long data);
 static void epic_tx_timeout(struct device *dev);
 static void epic_init_ring(struct device *dev);
 static int epic_start_xmit(struct sk_buff *skb, struct device *dev);
 static int epic_rx(struct device *dev);
 static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd);
 static int epic_close(struct device *dev);
-static struct enet_statistics *epic_get_stats(struct device *dev);
-#ifdef NEW_MULTICAST
+static struct net_device_stats *epic_get_stats(struct device *dev);
 static void set_rx_mode(struct device *dev);
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
 
 
-
-#ifdef MODULE
 /* A list of all installed EPIC devices, for removing the driver module. */
 static struct device *root_epic_dev = NULL;
-#endif
 
+#ifndef CARDBUS
 int epic100_probe(struct device *dev)
 {
 	int cards_found = 0;
-	static int pci_index = 0;	/* Static, for multiple probe calls. */
-
-	/* Ideally we would detect all network cards in slot order.  That would
-	   be best done a central PCI probe dispatch, which wouldn't work
-	   well with the current structure.  So instead we detect just the
-	   Epic cards in slot order. */
+	int chip_idx, irq;
+	u16 pci_command, new_command;
+	unsigned char pci_bus, pci_device_fn;
+
+#ifdef PCI_SUPPORT_VER2
+	struct pci_dev *pcidev = NULL;
+	while ((pcidev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pcidev))
+			!= NULL) {
+		long pci_ioaddr = pcidev->base_address[0] & ~3;
+		int vendor = pcidev->vendor;
+		int device = pcidev->device;
+
+		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+			if (vendor == chip_tbl[chip_idx].vendor_id
+				&& (device & chip_tbl[chip_idx].device_id_mask) ==
+				chip_tbl[chip_idx].device_id)
+				break;
+		if (chip_tbl[chip_idx].vendor_id == 0 		/* Compiled out! */
+			||	check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+			continue;
+		pci_bus = pcidev->bus->number;
+		pci_device_fn = pcidev->devfn;
+		irq = pcidev->irq;
+#else
+	int pci_index;
 
-	if (pci_present()) {
-		unsigned char pci_bus, pci_device_fn;
+	if ( ! pcibios_present())
+		return -ENODEV;
 
-		for (;pci_index < 0xff; pci_index++) {
-#if LINUX_VERSION_CODE >= 0x20155
-			unsigned int pci_irq_line;
-			struct pci_dev *pdev;
-#else
-			unsigned char pci_irq_line;
-#endif
-			unsigned char pci_latency;
-			unsigned short pci_command, vendor, device;
-			unsigned int pci_ioaddr, chip_idx = 0;
-
-			if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
-#ifdef REVERSE_PROBE_ORDER
-									0xff - pci_index,
-#else
-									pci_index,
-#endif
-									&pci_bus, &pci_device_fn)
-				!= PCIBIOS_SUCCESSFUL)
+	for (pci_index = 0; pci_index < 0xff; pci_index++) {
+		u8 pci_irq_line;
+		u16 vendor, device;
+		u32 pci_ioaddr;
+
+		if (pcibios_find_class (PCI_CLASS_NETWORK_ETHERNET << 8,
+								pci_index, &pci_bus, &pci_device_fn)
+			!= PCIBIOS_SUCCESSFUL)
+			break;
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_VENDOR_ID, &vendor);
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_DEVICE_ID, &device);
+
+		for (chip_idx = 0; chip_tbl[chip_idx].vendor_id; chip_idx++)
+			if (vendor == chip_tbl[chip_idx].vendor_id
+				&& (device & chip_tbl[chip_idx].device_id_mask) ==
+				chip_tbl[chip_idx].device_id)
 				break;
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_VENDOR_ID, &vendor);
-			if (vendor != PCI_VENDOR_ID_SMC)
-				continue;
+		if (chip_tbl[chip_idx].vendor_id == 0) 		/* Compiled out! */
+			continue;
 
-			pcibios_read_config_word(pci_bus, pci_device_fn,
-									 PCI_DEVICE_ID, &device);
-#if LINUX_VERSION_CODE >= 0x20155
-			pdev = pci_find_slot(pci_bus, pci_device_fn);
-			pci_irq_line = pdev->irq;
-			pci_ioaddr = pdev->base_address[0];
-#else
-			pcibios_read_config_byte(pci_bus, pci_device_fn,
-									 PCI_INTERRUPT_LINE, &pci_irq_line);
-			pcibios_read_config_dword(pci_bus, pci_device_fn,
-									  PCI_BASE_ADDRESS_0, &pci_ioaddr);
-#endif
-			/* Remove I/O space marker in bit 0. */
-			pci_ioaddr &= ~3;
-
-			if (device != PCI_DEVICE_ID_SMC_EPIC100) {
-				printk("Unknown SMC PCI ethernet chip type %4.4x detected:"
-					   " not configured.\n", device);
-				continue;
-			}
-			if (epic_debug > 2)
-				printk("Found SMC PCI EPIC/100 at I/O %#x, IRQ %d.\n",
-					   pci_ioaddr, pci_irq_line);
-
-			if (check_region(pci_ioaddr, EPIC_TOTAL_SIZE))
-				continue;
+		pcibios_read_config_dword(pci_bus, pci_device_fn,
+								  PCI_BASE_ADDRESS_0, &pci_ioaddr);
+		pcibios_read_config_byte(pci_bus, pci_device_fn,
+								 PCI_INTERRUPT_LINE, &pci_irq_line);
+		/* Remove I/O space marker in bit 0. */
+		pci_ioaddr &= ~3;
+		irq = pci_irq_line;
+
+		if (check_region(pci_ioaddr, chip_tbl[chip_idx].io_size))
+			continue;
+#endif
+
+		/* EPIC-specific code: Soft-reset the chip ere setting as master. */
+		outl(0x0001, pci_ioaddr + GENCTL);
+
+		/* Activate the card: fix for brain-damaged Win98 BIOSes. */
+		pcibios_read_config_word(pci_bus, pci_device_fn,
+								 PCI_COMMAND, &pci_command);
+		new_command = pci_command | PCI_COMMAND_MASTER|PCI_COMMAND_IO;
+		if (pci_command != new_command) {
+			printk(KERN_INFO "  The PCI BIOS has not enabled Ethernet"
+				   " device %4.4x-%4.4x."
+				   "  Updating PCI command %4.4x->%4.4x.\n",
+				   vendor, device, pci_command, new_command);
+			pcibios_write_config_word(pci_bus, pci_device_fn,
+									  PCI_COMMAND, new_command);
+		}
 
-#ifdef MODULE
-			dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
-						 options[cards_found], cards_found);
-#else
-			dev = epic100_probe1(dev, pci_ioaddr, pci_irq_line, chip_idx,
-						 dev ? dev->mem_start : 0, -1);
-#endif
+		dev = chip_tbl[chip_idx].probe1(pci_bus, pci_device_fn, dev, pci_ioaddr,
+									   irq, chip_idx, cards_found);
 
-			if (dev) {
-			  /* Get and check the bus-master and latency values. */
-			  pcibios_read_config_word(pci_bus, pci_device_fn,
-									   PCI_COMMAND, &pci_command);
-			  if ( ! (pci_command & PCI_COMMAND_MASTER)) {
-				printk("  PCI Master Bit has not been set! Setting...\n");
-				pci_command |= PCI_COMMAND_MASTER;
-				pcibios_write_config_word(pci_bus, pci_device_fn,
-										  PCI_COMMAND, pci_command);
-			  }
-			  pcibios_read_config_byte(pci_bus, pci_device_fn,
-									   PCI_LATENCY_TIMER, &pci_latency);
-			  if (pci_latency < 10) {
-				printk("  PCI latency timer (CFLT) is unreasonably low at %d."
-					   "  Setting to 255 clocks.\n", pci_latency);
+		/* Check the latency timer. */
+		if (dev) {
+			u8 pci_latency;
+			pcibios_read_config_byte(pci_bus, pci_device_fn,
+									 PCI_LATENCY_TIMER, &pci_latency);
+			if (pci_latency < chip_tbl[chip_idx].min_latency) {
+				printk(KERN_INFO "  PCI latency timer (CFLT) value of %d is "
+					   "unreasonably low, setting to %d.\n", pci_latency,
+					   chip_tbl[chip_idx].min_latency);
 				pcibios_write_config_byte(pci_bus, pci_device_fn,
-										  PCI_LATENCY_TIMER, 255);
-			  } else if (epic_debug > 1)
-				printk("  PCI latency timer (CFLT) is %#x.\n", pci_latency);
-			  dev = 0;
-			  cards_found++;
+										  PCI_LATENCY_TIMER,
+										  chip_tbl[chip_idx].min_latency);
 			}
+			dev = 0;
+			cards_found++;
 		}
 	}
 
-#if defined (MODULE)
-	return cards_found;
-#else
 	return cards_found ? 0 : -ENODEV;
-#endif
 }
+#endif  /* not CARDBUS */
 
-static struct device *epic100_probe1(struct device *dev, int ioaddr, int irq,
-								   int chip_id, int options, int card_idx)
+static struct device *epic_probe1(int pci_bus, int pci_devfn,
+								  struct device *dev, long ioaddr, int irq,
+								  int chip_idx, int card_idx)
 {
-	static int did_version = 0;			/* Already printed version info. */
-	struct epic_private *tp;
-	int i;
+	struct epic_private *ep;
+	int i, option = 0, duplex = 0;
 
-	if (epic_debug > 0  &&  did_version++ == 0)
-		printk(version);
+	if (dev && dev->mem_start) {
+		option = dev->mem_start;
+		duplex = (dev->mem_start & 16) ? 1 : 0;
+	} else if (card_idx >= 0  &&  card_idx < MAX_UNITS) {
+		if (options[card_idx] >= 0)
+			option = options[card_idx];
+		if (full_duplex[card_idx] >= 0)
+			duplex = full_duplex[card_idx];
+	}
 
 	dev = init_etherdev(dev, 0);
 
-	printk("%s: SMC EPIC/100 at %#3x, IRQ %d, ", dev->name, ioaddr, irq);
+	dev->base_addr = ioaddr;
+	dev->irq = irq;
+	printk(KERN_INFO "%s: SMC EPIC/100 at %#lx, IRQ %d, ",
+		   dev->name, ioaddr, dev->irq);
 
 	/* Bring the chip out of low-power mode. */
-	outl(0x0200, ioaddr + GENCTL);
+	outl(0x4200, ioaddr + GENCTL);
 	/* Magic?!  If we don't set this bit the MII interface won't work. */
 	outl(0x0008, ioaddr + TEST1);
 
+	/* Turn on the MII transceiver. */
+	outl(0x12, ioaddr + MIICfg);
+	if (chip_idx == 1)
+		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+	outl(0x0200, ioaddr + GENCTL);
+
 	/* This could also be read from the EEPROM. */
 	for (i = 0; i < 3; i++)
 		((u16 *)dev->dev_addr)[i] = inw(ioaddr + LAN0 + i*4);
@@ -416,65 +427,68 @@
 	printk("%2.2x.\n", dev->dev_addr[i]);
 
 	if (epic_debug > 1) {
-	  printk("%s: EEPROM contents\n", dev->name);
-	  for (i = 0; i < 64; i++)
-		printk(" %4.4x%s", read_eeprom(ioaddr, i), i % 16 == 15 ? "\n" : "");
+		printk(KERN_DEBUG "%s: EEPROM contents\n", dev->name);
+		for (i = 0; i < 64; i++)
+			printk(" %4.4x%s", read_eeprom(ioaddr, i),
+				   i % 16 == 15 ? "\n" : "");
 	}
 
 	/* We do a request_region() to register /proc/ioports info. */
-	request_region(ioaddr, EPIC_TOTAL_SIZE, "SMC EPIC/100");
-
-	dev->base_addr = ioaddr;
-	dev->irq = irq;
+	request_region(ioaddr, EPIC_TOTAL_SIZE, dev->name);
 
 	/* The data structures must be quadword aligned. */
-	tp = kmalloc(sizeof(*tp), GFP_KERNEL | GFP_DMA);
-	memset(tp, 0, sizeof(*tp));
-	dev->priv = tp;
+	ep = kmalloc(sizeof(*ep), GFP_KERNEL | GFP_DMA);
+	memset(ep, 0, sizeof(*ep));
+	dev->priv = ep;
 
-#ifdef MODULE
-	tp->next_module = root_epic_dev;
+	ep->next_module = root_epic_dev;
 	root_epic_dev = dev;
-#endif
 
-	tp->chip_id = chip_id;
+	ep->pci_bus = pci_bus;
+	ep->pci_dev_fn = pci_devfn;
+#if defined(PCI_SUPPORT_VER2)
+	ep->chip_id = pci_find_slot(pci_bus, pci_devfn)->device;
+#else
+	ep->chip_id = chip_tbl[chip_idx].device_id;
+#endif
 
 	/* Find the connected MII xcvrs.
 	   Doing this in open() would allow detecting external xcvrs later, but
 	   takes too much time. */
 	{
 		int phy, phy_idx;
-		for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);
+		for (phy = 1, phy_idx = 0; phy < 32 && phy_idx < sizeof(ep->phys);
 			 phy++) {
-			int mii_status = mii_read(ioaddr, phy, 0);
+			int mii_status = mdio_read(ioaddr, phy, 1);
 			if (mii_status != 0xffff  && mii_status != 0x0000) {
-				tp->phys[phy_idx++] = phy;
-				printk("%s: MII transceiver found at address %d.\n",
-					   dev->name, phy);
+				ep->phys[phy_idx++] = phy;
+				printk(KERN_INFO "%s: MII transceiver #%d control "
+					   "%4.4x status %4.4x.\n"
+					   KERN_INFO "%s:  Autonegotiation advertising %4.4x "
+					   "link partner %4.4x.\n",
+					   dev->name, phy, mdio_read(ioaddr, phy, 0), mii_status,
+					   dev->name, mdio_read(ioaddr, phy, 4),
+					   mdio_read(ioaddr, phy, 5));
 			}
 		}
 		if (phy_idx == 0) {
-			printk("%s: ***WARNING***: No MII transceiver found!\n",
+			printk(KERN_WARNING "%s: ***WARNING***: No MII transceiver found!\n",
 				   dev->name);
 			/* Use the known PHY address of the EPII. */
-			tp->phys[0] = 3;
+			ep->phys[0] = 3;
 		}
 	}
 
-	/* Leave the chip in low-power mode. */
+	/* Turn off the MII xcvr (175 only!), leave the chip in low-power mode. */
+	if (ep->chip_id == 6)
+		outl(inl(ioaddr + NVCTL) & ~0x483C, ioaddr + NVCTL);
 	outl(0x0008, ioaddr + GENCTL);
 
 	/* The lower four bits are the media type. */
-	if (options > 0) {
-		tp->full_duplex = (options & 16) ? 1 : 0;
-		tp->default_port = options & 15;
-		if (tp->default_port)
-		  tp->medialock = 1;
-	}
-	if (card_idx >= 0) {
-		if (full_duplex[card_idx] >= 0)
-			tp->full_duplex = full_duplex[card_idx];
-	}
+	ep->force_fd = duplex;
+	ep->default_port = option;
+	if (ep->default_port)
+		ep->medialock = 1;
 
 	/* The Epic-specific entries in the device structure. */
 	dev->open = &epic_open;
@@ -482,6 +496,7 @@
 	dev->stop = &epic_close;
 	dev->get_stats = &epic_get_stats;
 	dev->set_multicast_list = &set_rx_mode;
+	dev->do_ioctl = &mii_ioctl;
 
 	return dev;
 }
@@ -498,41 +513,42 @@
 #define EE_ENB			(0x0001 | EE_CS)
 
 /* Delay between EEPROM clock transitions.
-   The 1.2 code is a "nasty" timing loop, but PC compatible machines are
-   *supposed* to delay an ISA-compatible period for the SLOW_DOWN_IO macro.  */
+   No extra delay is needed with 33Mhz PCI, but 66Mhz is untested.
+ */
+
 #ifdef _LINUX_DELAY_H
-#define eeprom_delay(nanosec)	udelay((nanosec + 999)/1000)
+#define eeprom_delay(nanosec)	udelay(1)
 #else
-#define eeprom_delay(nanosec)	do { int _i = 3; while (--_i > 0) { __SLOW_DOWN_IO; }} while (0)
+#define eeprom_delay(nanosec)	do { ; } while (0)
 #endif
 
 /* The EEPROM commands include the alway-set leading bit. */
 #define EE_WRITE_CMD	(5 << 6)
-#define EE_READ_CMD		(6 << 6)
+#define EE_READ64_CMD	(6 << 6)
+#define EE_READ256_CMD	(6 << 8)
 #define EE_ERASE_CMD	(7 << 6)
 
-static int read_eeprom(int ioaddr, int location)
+static int read_eeprom(long ioaddr, int location)
 {
 	int i;
 	int retval = 0;
-	int ee_addr = ioaddr + EECTL;
-	int read_cmd = location | EE_READ_CMD;
-	
+	long ee_addr = ioaddr + EECTL;
+	int read_cmd = location |
+		(inl(ee_addr) & 0x40) ? EE_READ64_CMD : EE_READ256_CMD;
+
 	outl(EE_ENB & ~EE_CS, ee_addr);
 	outl(EE_ENB, ee_addr);
-	
+
 	/* Shift the read command bits out. */
-	for (i = 10; i >= 0; i--) {
-		short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+	for (i = 12; i >= 0; i--) {
+		short dataval = (read_cmd & (1 << i)) ? EE_WRITE_1 : EE_WRITE_0;
 		outl(EE_ENB | dataval, ee_addr);
 		eeprom_delay(100);
 		outl(EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
 		eeprom_delay(150);
-		outl(EE_ENB | dataval, ee_addr);	/* Finish EEPROM a clock tick. */
-		eeprom_delay(250);
 	}
 	outl(EE_ENB, ee_addr);
-	
+
 	for (i = 16; i > 0; i--) {
 		outl(EE_ENB | EE_SHIFT_CLK, ee_addr);
 		eeprom_delay(100);
@@ -548,7 +564,7 @@
 
 #define MII_READOP		1
 #define MII_WRITEOP		2
-static int mii_read(int ioaddr, int phy_id, int location)
+static int mdio_read(long ioaddr, int phy_id, int location)
 {
 	int i;
 
@@ -556,66 +572,82 @@
 	/* Typical operation takes < 50 ticks. */
 	for (i = 4000; i > 0; i--)
 		if ((inl(ioaddr + MIICtrl) & MII_READOP) == 0)
+			return inw(ioaddr + MIIData);
+	return 0xffff;
+}
+
+static void mdio_write(long ioaddr, int phy_id, int location, int value)
+{
+	int i;
+
+	outw(value, ioaddr + MIIData);
+	outl((phy_id << 9) | (location << 4) | MII_WRITEOP, ioaddr + MIICtrl);
+	for (i = 10000; i > 0; i--) {
+		if ((inl(ioaddr + MIICtrl) & MII_WRITEOP) == 0)
 			break;
-	return inw(ioaddr + MIIData);
+	}
+	return;
 }
 
 
 static int
 epic_open(struct device *dev)
 {
-	struct epic_private *tp = (struct epic_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
 	int i;
 	int mii_reg5;
-	int full_duplex = 0;
+	ep->full_duplex = ep->force_fd;
 
 	/* Soft reset the chip. */
-	outl(0x0001, ioaddr + GENCTL);
+	outl(0x4001, ioaddr + GENCTL);
 
-#ifdef SA_SHIRQ
-	if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ,
-					"SMC EPIC/100", dev)) {
-		return -EAGAIN;
-	}
-#else
-	if (irq2dev_map[dev->irq] != NULL
-		|| (irq2dev_map[dev->irq] = dev) == NULL
-		|| dev->irq == 0
-		|| request_irq(dev->irq, &epic_interrupt, 0, "SMC EPIC/100")) {
+	if (request_irq(dev->irq, &epic_interrupt, SA_SHIRQ, "SMC EPIC/100", dev))
 		return -EAGAIN;
-	}
-#endif
 
 	MOD_INC_USE_COUNT;
 
 	epic_init_ring(dev);
 
-	/* This next line by Ken Yamaguchi.. ?? */
-	outl(0x8, ioaddr + 0x1c);
+	outl(0x4000, ioaddr + GENCTL);
+	/* This next magic! line by Ken Yamaguchi.. ?? */
+	outl(0x0008, ioaddr + TEST1);
+
+	/* Pull the chip out of low-power mode, enable interrupts, and set for
+	   PCI read multiple.  The MIIcfg setting and strange write order are
+	   required by the details of which bits are reset and the transceiver
+	   wiring on the Ositech CardBus card.
+	*/
+	outl(0x12, ioaddr + MIICfg);
+	if (ep->chip_id == 6)
+		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
 
-	/* Pull the chip out of low-power mode, enable interrupts, and set for PCI read multiple. */
+#if defined(__powerpc__) || defined(__sparc__)		/* Big endian */
+	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#else
 	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#endif
 
 	for (i = 0; i < 3; i++)
 		outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
 
 	outl(TX_FIFO_THRESH, ioaddr + TxThresh);
-	full_duplex = tp->full_duplex;
 
-	mii_reg5 = mii_read(ioaddr, tp->phys[0], 5);
-	if (mii_reg5 != 0xffff && (mii_reg5 & 0x0100)) {
-		full_duplex = 1;
+	mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
+	if (mii_reg5 != 0xffff) {
+		if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)
+			ep->full_duplex = 1;
+		else if (! (mii_reg5 & 0x4000))
+			mdio_write(ioaddr, ep->phys[0], 0, 0x1200);
 		if (epic_debug > 1)
-			printk("%s: Setting %s-duplex based on MII xcvr %d"
+			printk(KERN_INFO "%s: Setting %s-duplex based on MII xcvr %d"
 				   " register read of %4.4x.\n", dev->name,
-				   full_duplex ? "full" : "half", tp->phys[0],
-				   mii_read(ioaddr, tp->phys[0], 5));
+				   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
 	}
 
-	outl(full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
-	outl(virt_to_bus(tp->rx_ring), ioaddr + PRxCDAR);
-	outl(virt_to_bus(tp->tx_ring), ioaddr + PTxCDAR);
+	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(virt_to_bus(ep->rx_ring), ioaddr + PRxCDAR);
+	outl(virt_to_bus(ep->tx_ring), ioaddr + PTxCDAR);
 
 	/* Start the chip's Rx process. */
 	set_rx_mode(dev);
@@ -626,67 +658,160 @@
 	dev->start = 1;
 
 	/* Enable interrupts by setting the interrupt mask. */
-	outl(CntFull | TxUnderrun | TxDone
+	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | TxDone
 		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
 		 ioaddr + INTMASK);
 
 	if (epic_debug > 1)
-		printk("%s: epic_open() ioaddr %4.4x IRQ %d status %4.4x %s-duplex.\n",
+		printk(KERN_DEBUG "%s: epic_open() ioaddr %lx IRQ %d status %4.4x "
+			   "%s-duplex.\n",
 			   dev->name, ioaddr, dev->irq, inl(ioaddr + GENCTL),
-			   full_duplex ? "full" : "half");
+			   ep->full_duplex ? "full" : "half");
 
 	/* Set the timer to switch to check for link beat and perhaps switch
 	   to an alternate media type. */
-	init_timer(&tp->timer);
-	tp->timer.expires = RUN_AT((24*HZ)/10);			/* 2.4 sec. */
-	tp->timer.data = (unsigned long)dev;
-	tp->timer.function = &epic_timer;				/* timer handler */
-	add_timer(&tp->timer);
+	init_timer(&ep->timer);
+	ep->timer.expires = RUN_AT((24*HZ)/10);			/* 2.4 sec. */
+	ep->timer.data = (unsigned long)dev;
+	ep->timer.function = &epic_timer;				/* timer handler */
+	add_timer(&ep->timer);
 
 	return 0;
 }
 
+/* Reset the chip to recover from a PCI transaction error.
+   This may occur at interrupt time. */
+static void epic_pause(struct device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	outl(0x00000000, ioaddr + INTMASK);
+	/* Stop the chip's Tx and Rx DMA processes. */
+	outw(0x0061, ioaddr + COMMAND);
+
+	/* Update the error counts. */
+	if (inw(ioaddr + COMMAND) != 0xffff) {
+		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+		ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+	}
+
+	/* Remove the packets on the Rx queue. */
+	epic_rx(dev);
+}
+
+static void epic_restart(struct device *dev)
+{
+	long ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	int i;
+
+	printk(KERN_DEBUG "%s: Restarting the EPIC chip, Rx %d/%d Tx %d/%d.\n",
+		   dev->name, ep->cur_rx, ep->dirty_rx, ep->dirty_tx, ep->cur_tx);
+	/* Soft reset the chip. */
+	outl(0x0001, ioaddr + GENCTL);
+
+	udelay(1);
+	/* Duplicate code from epic_open(). */
+	outl(0x0008, ioaddr + TEST1);
+
+#if defined(__powerpc__)		/* Big endian */
+	outl(0x0432 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#else
+	outl(0x0412 | (RX_FIFO_THRESH<<8), ioaddr + GENCTL);
+#endif
+	outl(0x12, ioaddr + MIICfg);
+	if (ep->chip_id == 6)
+		outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+
+	for (i = 0; i < 3; i++)
+		outl(((u16*)dev->dev_addr)[i], ioaddr + LAN0 + i*4);
+
+	outl(TX_FIFO_THRESH, ioaddr + TxThresh);
+	outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+	outl(virt_to_bus(&ep->rx_ring[ep->cur_rx%RX_RING_SIZE]), ioaddr + PRxCDAR);
+	outl(virt_to_bus(&ep->tx_ring[ep->dirty_tx%TX_RING_SIZE]),
+		 ioaddr + PTxCDAR);
+
+	/* Start the chip's Rx process. */
+	set_rx_mode(dev);
+	outl(0x000A, ioaddr + COMMAND);
+
+	/* Enable interrupts by setting the interrupt mask. */
+	outl((ep->chip_id == 6 ? PCIBusErr175 : PCIBusErr170)
+		 | CntFull | TxUnderrun | TxDone
+		 | RxError | RxOverflow | RxFull | RxHeader | RxDone,
+		 ioaddr + INTMASK);
+	printk(KERN_DEBUG "%s: epic_restart() done, cmd status %4.4x, ctl %4.4x"
+		   " interrupt %4.4x.\n",
+			   dev->name, inl(ioaddr + COMMAND), inl(ioaddr + GENCTL),
+		   inl(ioaddr + INTSTAT));
+	return;
+}
+
 static void epic_timer(unsigned long data)
 {
 	struct device *dev = (struct device *)data;
-	struct epic_private *tp = (struct epic_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
 	int next_tick = 0;
+	int mii_reg5 = mdio_read(ioaddr, ep->phys[0], 5);
 
 	if (epic_debug > 3) {
-		printk("%s: Media selection tick, Tx status %8.8x.\n",
+		printk(KERN_DEBUG "%s: Media selection tick, Tx status %8.8x.\n",
 			   dev->name, inl(ioaddr + TxSTAT));
-		printk("%s: Other registers are IntMask %4.4x IntStatus %4.4x RxStatus"
-			   " %4.4x.\n",
+		printk(KERN_DEBUG "%s: Other registers are IntMask %4.4x "
+			   "IntStatus %4.4x RxStatus %4.4x.\n",
 			   dev->name, inl(ioaddr + INTMASK), inl(ioaddr + INTSTAT),
 			   inl(ioaddr + RxSTAT));
 	}
+	if (! ep->force_fd  &&  mii_reg5 != 0xffff) {
+		int duplex = (mii_reg5&0x0100) || (mii_reg5 & 0x01C0) == 0x0040;
+		if (ep->full_duplex != duplex) {
+			ep->full_duplex = duplex;
+			printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d link"
+				   " partner capability of %4.4x.\n", dev->name,
+				   ep->full_duplex ? "full" : "half", ep->phys[0], mii_reg5);
+			outl(ep->full_duplex ? 0x7F : 0x79, ioaddr + TxCtrl);
+		}
+		next_tick = 60*HZ;
+	}
 
 	if (next_tick) {
-		tp->timer.expires = RUN_AT(next_tick);
-		add_timer(&tp->timer);
+		ep->timer.expires = RUN_AT(next_tick);
+		add_timer(&ep->timer);
 	}
 }
 
 static void epic_tx_timeout(struct device *dev)
 {
-	struct epic_private *tp = (struct epic_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
 
 	if (epic_debug > 0) {
-		printk("%s: Transmit timeout using MII device, Tx status %4.4x.\n",
+		printk(KERN_WARNING "%s: Transmit timeout using MII device, "
+			   "Tx status %4.4x.\n",
 			   dev->name, inw(ioaddr + TxSTAT));
 		if (epic_debug > 1) {
-			printk("%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
-			 dev->name, tp->dirty_tx, tp->cur_tx);
+			printk(KERN_DEBUG "%s: Tx indices: dirty_tx %d, cur_tx %d.\n",
+			 dev->name, ep->dirty_tx, ep->cur_tx);
 		}
 	}
+	if (inw(ioaddr + TxSTAT) & 0x10) {		/* Tx FIFO underflow. */
+		ep->stats.tx_fifo_errors++;
+		/* Restart the transmit process. */
+		outl(0x0080, ioaddr + COMMAND);
+	}
+
 	/* Perhaps stop and restart the chip's Tx processes . */
 	/* Trigger a transmit demand. */
 	outl(0x0004, dev->base_addr + COMMAND);
 
 	dev->trans_start = jiffies;
-	tp->stats.tx_errors++;
+	ep->stats.tx_errors++;
 	return;
 }
 
@@ -694,66 +819,51 @@
 static void
 epic_init_ring(struct device *dev)
 {
-	struct epic_private *tp = (struct epic_private *)dev->priv;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int i;
 
-	tp->tx_full = 0;
-	tp->cur_rx = tp->cur_tx = 0;
-	tp->dirty_rx = tp->dirty_tx = 0;
+	ep->tx_full = 0;
+	ep->cur_rx = ep->cur_tx = 0;
+	ep->dirty_rx = ep->dirty_tx = 0;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		tp->rx_ring[i].status = 0x8000;		/* Owned by Epic chip */
-		tp->rx_ring[i].buflength = PKT_BUF_SZ;
+		ep->rx_ring[i].status = 0x8000;		/* Owned by Epic chip */
+		ep->rx_ring[i].buflength = PKT_BUF_SZ;
 		{
 			/* Note the receive buffer must be longword aligned.
 			   dev_alloc_skb() provides 16 byte alignment.  But do *not*
 			   use skb_reserve() to align the IP header! */
 			struct sk_buff *skb;
-			skb = DEV_ALLOC_SKB(PKT_BUF_SZ);
-			tp->rx_skbuff[i] = skb;
+			skb = dev_alloc_skb(PKT_BUF_SZ);
+			ep->rx_skbuff[i] = skb;
 			if (skb == NULL)
 				break;			/* Bad news!  */
 			skb->dev = dev;			/* Mark as being used by this device. */
-#if LINUX_VERSION_CODE > 0x10300
 			skb_reserve(skb, 2); /* Align IP on 16 byte boundaries */
-			tp->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
-#else
-			tp->rx_ring[i].bufaddr = virt_to_bus(skb->data);
-#endif
+			ep->rx_ring[i].bufaddr = virt_to_bus(skb->tail);
 		}
-		tp->rx_ring[i].next = virt_to_bus(&tp->rx_ring[i+1]);
+		ep->rx_ring[i].next = virt_to_bus(&ep->rx_ring[i+1]);
 	}
 	/* Mark the last entry as wrapping the ring. */
-	tp->rx_ring[i-1].next = virt_to_bus(&tp->rx_ring[0]);
+	ep->rx_ring[i-1].next = virt_to_bus(&ep->rx_ring[0]);
 
 	/* The Tx buffer descriptor is filled in as needed, but we
 	   do need to clear the ownership bit. */
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		tp->tx_skbuff[i] = 0;
-		tp->tx_ring[i].status = 0x0000;
-		tp->tx_ring[i].next = virt_to_bus(&tp->tx_ring[i+1]);
+		ep->tx_skbuff[i] = 0;
+		ep->tx_ring[i].status = 0x0000;
+		ep->tx_ring[i].next = virt_to_bus(&ep->tx_ring[i+1]);
 	}
-	tp->tx_ring[i-1].next = virt_to_bus(&tp->tx_ring[0]);
+	ep->tx_ring[i-1].next = virt_to_bus(&ep->tx_ring[0]);
 }
 
 static int
 epic_start_xmit(struct sk_buff *skb, struct device *dev)
 {
-	struct epic_private *tp = (struct epic_private *)dev->priv;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int entry;
 	u32 flag;
 
-#ifndef final_version
-	if (skb == NULL || skb->len <= 0) {
-		printk("%s: Obsolete driver layer request made: skbuff==NULL.\n",
-			   dev->name);
-#if 0
-		dev_tint(dev);
-#endif
-		return 0;
-	}
-#endif
-
 	/* 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) {
@@ -767,37 +877,37 @@
 	   with the "ownership" bits last. */
 
 	/* Calculate the next Tx descriptor entry. */
-	entry = tp->cur_tx % TX_RING_SIZE;
+	entry = ep->cur_tx % TX_RING_SIZE;
 
-	tp->tx_skbuff[entry] = skb;
-	tp->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
-	tp->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
-	tp->tx_ring[entry].buflength = skb->len;
+	ep->tx_skbuff[entry] = skb;
+	ep->tx_ring[entry].txlength = (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN);
+	ep->tx_ring[entry].bufaddr = virt_to_bus(skb->data);
+	ep->tx_ring[entry].buflength = skb->len;
 
-	if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
+	if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE/2) {/* Typical path */
 	  flag = 0x10; /* No interrupt */
-	  dev->tbusy = 0;
-	} else if (tp->cur_tx - tp->dirty_tx == TX_RING_SIZE/2) {
+	  clear_bit(0, (void*)&dev->tbusy);
+	} else if (ep->cur_tx - ep->dirty_tx == TX_RING_SIZE/2) {
 	  flag = 0x14; /* Tx-done intr. */
-	  dev->tbusy = 0;
-	} else if (tp->cur_tx - tp->dirty_tx < TX_RING_SIZE - 2) {
+	  clear_bit(0, (void*)&dev->tbusy);
+	} else if (ep->cur_tx - ep->dirty_tx < TX_RING_SIZE - 2) {
 	  flag = 0x10; /* No Tx-done intr. */
-	  dev->tbusy = 0;
+	  clear_bit(0, (void*)&dev->tbusy);
 	} else {
 	  /* Leave room for two additional entries. */
 	  flag = 0x14; /* Tx-done intr. */
-	  tp->tx_full = 1;
+	  ep->tx_full = 1;
 	}
 
-	tp->tx_ring[entry].control = flag;
-	tp->tx_ring[entry].status = 0x8000;	/* Pass ownership to the chip. */
-	tp->cur_tx++;
+	ep->tx_ring[entry].control = flag;
+	ep->tx_ring[entry].status = 0x8000;	/* Pass ownership to the chip. */
+	ep->cur_tx++;
 	/* Trigger an immediate transmit demand. */
 	outl(0x0004, dev->base_addr + COMMAND);
 
 	dev->trans_start = jiffies;
 	if (epic_debug > 4)
-		printk("%s: Queued Tx packet size %d to slot %d, "
+		printk(KERN_DEBUG "%s: Queued Tx packet size %d to slot %d, "
 			   "flag %2.2x Tx status %8.8x.\n",
 			   dev->name, (int)skb->len, entry, flag,
 			   inl(dev->base_addr + TxSTAT));
@@ -807,27 +917,28 @@
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static void epic_interrupt IRQ(int irq, void *dev_instance, struct pt_regs *regs)
+static void epic_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
 {
-#ifdef SA_SHIRQ
 	struct device *dev = (struct device *)dev_instance;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	int status, boguscnt = max_interrupt_work;
+
+#if defined(__i386__)
+	/* A lock to prevent simultaneous entry bug on Intel SMP machines. */
+	if (test_and_set_bit(0, (void*)&dev->interrupt)) {
+		printk(KERN_ERR"%s: SMP simultaneous entry of an interrupt handler.\n",
+			   dev->name);
+		dev->interrupt = 0;	/* Avoid halting machine. */
+		return;
+	}
 #else
-	struct device *dev = (struct device *)(irq2dev_map[irq]);
-#endif
-	struct epic_private *lp;
-	int status, ioaddr, boguscnt = max_interrupt_work;
-
-	if (dev == NULL) {
-		printk ("epic_interrupt(): irq %d for unknown device.\n", irq);
+	if (dev->interrupt) {
+		printk(KERN_ERR "%s: Re-entering the interrupt handler.\n", dev->name);
 		return;
 	}
-
-	ioaddr = dev->base_addr;
-	lp = (struct epic_private *)dev->priv;
-	if (dev->interrupt)
-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
-
 	dev->interrupt = 1;
+#endif
 
 	do {
 		status = inl(ioaddr + INTSTAT);
@@ -838,18 +949,18 @@
 			printk("%s: interrupt  interrupt=%#8.8x new intstat=%#8.8x.\n",
 				   dev->name, status, inl(ioaddr + INTSTAT));
 
-		if ((status & (RxDone | TxEmpty | TxDone)) == 0)
+		if ((status & IntrSummary) == 0)
 			break;
 
-		if (status & RxDone)			/* Rx interrupt */
+		if (status & (RxDone | RxStarted | RxEarlyWarn))
 			epic_rx(dev);
 
 		if (status & (TxEmpty | TxDone)) {
 			int dirty_tx;
 
-			for (dirty_tx = lp->dirty_tx; dirty_tx < lp->cur_tx; dirty_tx++) {
+			for (dirty_tx = ep->dirty_tx; dirty_tx < ep->cur_tx; dirty_tx++) {
 				int entry = dirty_tx % TX_RING_SIZE;
-				int txstatus = lp->tx_ring[entry].status;
+				int txstatus = ep->tx_ring[entry].status;
 
 				if (txstatus < 0)
 					break;			/* It still hasn't been Txed */
@@ -861,66 +972,77 @@
 						printk("%s: Transmit error, Tx status %8.8x.\n",
 							   dev->name, txstatus);
 #endif
-					lp->stats.tx_errors++;
-					if (txstatus & 0x1050) lp->stats.tx_aborted_errors++;
-					if (txstatus & 0x0008) lp->stats.tx_carrier_errors++;
-					if (txstatus & 0x0040) lp->stats.tx_window_errors++;
-					if (txstatus & 0x0010) lp->stats.tx_fifo_errors++;
+					ep->stats.tx_errors++;
+					if (txstatus & 0x1050) ep->stats.tx_aborted_errors++;
+					if (txstatus & 0x0008) ep->stats.tx_carrier_errors++;
+					if (txstatus & 0x0040) ep->stats.tx_window_errors++;
+					if (txstatus & 0x0010) ep->stats.tx_fifo_errors++;
 #ifdef ETHER_STATS
-					if (txstatus & 0x1000) lp->stats.collisions16++;
+					if (txstatus & 0x1000) ep->stats.collisions16++;
 #endif
 				} else {
 #ifdef ETHER_STATS
-					if ((txstatus & 0x0002) != 0) lp->stats.tx_deferred++;
+					if ((txstatus & 0x0002) != 0) ep->stats.tx_deferred++;
 #endif
-					lp->stats.collisions += (txstatus >> 8) & 15;
-					lp->stats.tx_packets++;
+					ep->stats.collisions += (txstatus >> 8) & 15;
+					ep->stats.tx_packets++;
 				}
 
 				/* Free the original skb. */
-				dev_kfree_skb(lp->tx_skbuff[entry]);
-				lp->tx_skbuff[entry] = 0;
+				DEV_FREE_SKB(ep->tx_skbuff[entry]);
+				ep->tx_skbuff[entry] = 0;
 			}
 
 #ifndef final_version
-			if (lp->cur_tx - dirty_tx > TX_RING_SIZE) {
+			if (ep->cur_tx - dirty_tx > TX_RING_SIZE) {
 				printk("%s: Out-of-sync dirty pointer, %d vs. %d, full=%d.\n",
-					   dev->name, dirty_tx, lp->cur_tx, lp->tx_full);
+					   dev->name, dirty_tx, ep->cur_tx, ep->tx_full);
 				dirty_tx += TX_RING_SIZE;
 			}
 #endif
 
-			if (lp->tx_full && dev->tbusy
-				&& dirty_tx > lp->cur_tx - TX_RING_SIZE + 2) {
+			if (ep->tx_full && dev->tbusy
+				&& dirty_tx > ep->cur_tx - TX_RING_SIZE + 2) {
 				/* The ring is no longer full, clear tbusy. */
-				lp->tx_full = 0;
-				dev->tbusy = 0;
+				ep->tx_full = 0;
+				clear_bit(0, (void*)&dev->tbusy);
 				mark_bh(NET_BH);
 			}
 
-			lp->dirty_tx = dirty_tx;
+			ep->dirty_tx = dirty_tx;
 		}
 
 		/* Check uncommon events all at once. */
-		if (status & (CntFull | TxUnderrun | RxOverflow)) {
+		if (status & (CntFull | TxUnderrun | RxOverflow |
+					  PCIBusErr170 | PCIBusErr175)) {
+			if (status == 0xffffffff) /* Chip failed or removed (CardBus). */
+				break;
 			/* Always update the error counts to avoid overhead later. */
-			lp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-			lp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-			lp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+			ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+			ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+			ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
 
 			if (status & TxUnderrun) { /* Tx FIFO underflow. */
-			  lp->stats.tx_fifo_errors++;
-			  /* Restart the transmit process. */
-			  outl(0x0080, ioaddr + COMMAND);
+				ep->stats.tx_fifo_errors++;
+				outl(1536, ioaddr + TxThresh);
+				/* Restart the transmit process. */
+				outl(0x0080, ioaddr + COMMAND);
 			}
 			if (status & RxOverflow) {		/* Missed a Rx frame. */
-				lp->stats.rx_errors++;
+				ep->stats.rx_errors++;
+			}
+			if (status & PCIBusErr170) {
+				printk(KERN_ERR "%s: PCI Bus Error!  EPIC status %4.4x.\n",
+					   dev->name, status);
+				epic_pause(dev);
+				epic_restart(dev);
 			}
 			/* Clear all error sources. */
 			outl(status & 0x7f18, ioaddr + INTSTAT);
 		}
 		if (--boguscnt < 0) {
-			printk("%s: Too much work at interrupt, IntrStatus=0x%8.8x.\n",
+			printk(KERN_ERR "%s: Too much work at interrupt, "
+				   "IntrStatus=0x%8.8x.\n",
 				   dev->name, status);
 			/* Clear all interrupt sources. */
 			outl(0x0001ffff, ioaddr + INTSTAT);
@@ -929,133 +1051,101 @@
 	} while (1);
 
 	if (epic_debug > 3)
-		printk("%s: exiting interrupt, intr_status=%#4.4x.\n",
+		printk(KERN_DEBUG "%s: exiting interrupt, intr_status=%#4.4x.\n",
 			   dev->name, inl(ioaddr + INTSTAT));
 
-	/* Code that should never be run!  Perhaps remove after testing.. */
-	{
-		static int stopit = 10;
-		if (dev->start == 0  &&  --stopit < 0) {
-			printk("%s: Emergency stop, looping startup interrupt.\n",
-				   dev->name);
-			FREE_IRQ(irq, dev);
-		}
-	}
-
+#if defined(__i386__)
+	clear_bit(0, (void*)&dev->interrupt);
+#else
 	dev->interrupt = 0;
+#endif
 	return;
 }
 
-static int
-epic_rx(struct device *dev)
+static int epic_rx(struct device *dev)
 {
-	struct epic_private *lp = (struct epic_private *)dev->priv;
-	int entry = lp->cur_rx % RX_RING_SIZE;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	int entry = ep->cur_rx % RX_RING_SIZE;
+	int work_done = 0;
 
 	if (epic_debug > 4)
-		printk(" In epic_rx(), entry %d %8.8x.\n", entry,
-			   lp->rx_ring[entry].status);
+		printk(KERN_DEBUG " In epic_rx(), entry %d %8.8x.\n", entry,
+			   ep->rx_ring[entry].status);
 	/* If we own the next entry, it's a new packet. Send it up. */
-	while (lp->rx_ring[entry].status >= 0) {
-		int status = lp->rx_ring[entry].status;
+	while (ep->rx_ring[entry].status >= 0  &&  ep->rx_skbuff[entry]) {
+		int status = ep->rx_ring[entry].status;
 
 		if (epic_debug > 4)
-			printk("  epic_rx() status was %8.8x.\n", status);
-		if (status & 0x2000) {
-			printk("%s: Oversized Ethernet frame spanned multiple buffers,"
-				   " status %4.4x!\n", dev->name, status);
-			  lp->stats.rx_length_errors++;
-		} else if (status & 0x0006) {
-			/* Rx Frame errors are counted in hardware. */
-			lp->stats.rx_errors++;
+			printk(KERN_DEBUG "  epic_rx() status was %8.8x.\n", status);
+		if (status & 0x2006) {
+			if (status & 0x2000) {
+				printk(KERN_WARNING "%s: Oversized Ethernet frame spanned "
+					   "multiple buffers, status %4.4x!\n", dev->name, status);
+				ep->stats.rx_length_errors++;
+			} else if (status & 0x0006)
+				/* Rx Frame errors are counted in hardware. */
+				ep->stats.rx_errors++;
 		} else {
 			/* Malloc up new buffer, compatible with net-2e. */
 			/* Omit the four octet CRC from the length. */
-			short pkt_len = lp->rx_ring[entry].rxlength - 4;
+			short pkt_len = ep->rx_ring[entry].rxlength - 4;
 			struct sk_buff *skb;
-			int rx_in_place = 0;
 
-			/* Check if the packet is long enough to just accept without
-			   copying to a properly sized skbuff. */
-			if (pkt_len > rx_copybreak) {
-				struct sk_buff *newskb;
-				char *temp;
-
-				/* Pass up the skb already on the Rx ring. */
-				skb = lp->rx_skbuff[entry];
-				temp = skb_put(skb, pkt_len);
-				if (bus_to_virt(lp->rx_ring[entry].bufaddr) != temp)
-					printk("%s: Warning -- the skbuff addresses do not match"
-						   " in epic_rx: %p vs. %p / %p.\n", dev->name,
-						   bus_to_virt(lp->rx_ring[entry].bufaddr),
-						   skb->head, temp);
-				/* Get a fresh skbuff to replace the filled one. */
-				newskb = DEV_ALLOC_SKB(PKT_BUF_SZ);
-				if (newskb) {
-					rx_in_place = 1;
-					lp->rx_skbuff[entry] = newskb;
-					newskb->dev = dev;
-#if LINUX_VERSION_CODE > 0x10300
-					/* Align IP on 16 byte boundaries */
-					skb_reserve(newskb, 2);
-					lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->tail);
+			/* Check if the packet is long enough to accept without copying
+			   to a minimally-sized skbuff. */
+			if (pkt_len < rx_copybreak
+				&& (skb = dev_alloc_skb(pkt_len + 2)) != NULL) {
+				skb->dev = dev;
+				skb_reserve(skb, 2);	/* 16 byte align the IP header */
+#if 1 /* USE_IP_COPYSUM */
+				eth_copy_and_sum(skb, bus_to_virt(ep->rx_ring[entry].bufaddr),
+								 pkt_len, 0);
+				skb_put(skb, pkt_len);
 #else
-					lp->rx_ring[entry].bufaddr = virt_to_bus(newskb->data);
-#endif
-				} else			/* No memory, drop the packet. */
-				  skb = 0;
-			} else
-				skb = DEV_ALLOC_SKB(pkt_len + 2);
-			if (skb == NULL) {
-				int i;
-				printk("%s: Memory squeeze, deferring packet.\n", dev->name);
-				/* Check that at least two ring entries are free.
-				   If not, free one and mark stats->rx_dropped++. */
-				for (i = 0; i < RX_RING_SIZE; i++)
-					if (lp->rx_ring[(entry+i) % RX_RING_SIZE].status < 0)
-						break;
-
-				if (i > RX_RING_SIZE -2) {
-					lp->stats.rx_dropped++;
-					lp->rx_ring[entry].status = 0x8000;
-					lp->cur_rx++;
-				}
-				break;
-			}
-			skb->dev = dev;
-			if (! rx_in_place) {
-				skb_reserve(skb, 2);	/* 16 byte align the data fields */
 				memcpy(skb_put(skb, pkt_len),
-					   bus_to_virt(lp->rx_ring[entry].bufaddr), pkt_len);
+					   bus_to_virt(ep->rx_ring[entry].bufaddr), pkt_len);
+#endif
+			} else {
+				skb_put(skb = ep->rx_skbuff[entry], pkt_len);
+				ep->rx_skbuff[entry] = NULL;
 			}
-#if LINUX_VERSION_CODE > 0x10300
 			skb->protocol = eth_type_trans(skb, dev);
-#else
-			skb->len = pkt_len;
-#endif
 			netif_rx(skb);
-			lp->stats.rx_packets++;
+			ep->stats.rx_packets++;
 		}
-
-		lp->rx_ring[entry].status = 0x8000;
-		entry = (++lp->cur_rx) % RX_RING_SIZE;
+		work_done++;
+		entry = (++ep->cur_rx) % RX_RING_SIZE;
 	}
 
-	return 0;
+	/* Refill the Rx ring buffers. */
+	for (; ep->cur_rx - ep->dirty_rx > 0; ep->dirty_rx++) {
+		entry = ep->dirty_rx % RX_RING_SIZE;
+		if (ep->rx_skbuff[entry] == NULL) {
+			struct sk_buff *skb;
+			skb = ep->rx_skbuff[entry] = dev_alloc_skb(PKT_BUF_SZ);
+			if (skb == NULL)
+				break;
+			skb->dev = dev;			/* Mark as being used by this device. */
+			skb_reserve(skb, 2);	/* Align IP on 16 byte boundaries */
+			ep->rx_ring[entry].bufaddr = virt_to_bus(skb->tail);
+			work_done++;
+		}
+		ep->rx_ring[entry].status = 0x8000;
+	}
+	return work_done;
 }
 
-static int
-epic_close(struct device *dev)
+static int epic_close(struct device *dev)
 {
-	int ioaddr = dev->base_addr;
-	struct epic_private *tp = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
 	int i;
 
 	dev->start = 0;
 	dev->tbusy = 1;
 
 	if (epic_debug > 1)
-		printk("%s: Shutting down ethercard, status was %2.2x.\n",
+		printk(KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n",
 			   dev->name, inl(ioaddr + INTSTAT));
 
 	/* Disable interrupts by clearing the interrupt mask. */
@@ -1064,67 +1154,61 @@
 	outw(0x0061, ioaddr + COMMAND);
 
 	/* Update the error counts. */
-	tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-	tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-	tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+	ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+	ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+	ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
 
-	del_timer(&tp->timer);
+	del_timer(&ep->timer);
 
-#ifdef SA_SHIRQ
 	free_irq(dev->irq, dev);
-#else
-	free_irq(dev->irq);
-	irq2dev_map[dev->irq] = 0;
-#endif
 
 	/* Free all the skbuffs in the Rx queue. */
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		struct sk_buff *skb = tp->rx_skbuff[i];
-		tp->rx_skbuff[i] = 0;
-		tp->rx_ring[i].status = 0;		/* Not owned by Epic chip. */
-		tp->rx_ring[i].buflength = 0;
-		tp->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
+		struct sk_buff *skb = ep->rx_skbuff[i];
+		ep->rx_skbuff[i] = 0;
+		ep->rx_ring[i].status = 0;		/* Not owned by Epic chip. */
+		ep->rx_ring[i].buflength = 0;
+		ep->rx_ring[i].bufaddr = 0xBADF00D0; /* An invalid address. */
 		if (skb) {
 #if LINUX_VERSION_CODE < 0x20100
 			skb->free = 1;
 #endif
-			dev_kfree_skb(skb);
+			DEV_FREE_SKB(skb);
 		}
 	}
 	for (i = 0; i < TX_RING_SIZE; i++) {
-		if (tp->tx_skbuff[i])
-			dev_kfree_skb(tp->tx_skbuff[i]);
-		tp->tx_skbuff[i] = 0;
+		if (ep->tx_skbuff[i])
+			DEV_FREE_SKB(ep->tx_skbuff[i]);
+		ep->tx_skbuff[i] = 0;
 	}
 
 
 	/* Green! Leave the chip in low-power mode. */
 	outl(0x0008, ioaddr + GENCTL);
-	
+
 	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
 
-static struct enet_statistics *
-epic_get_stats(struct device *dev)
+static struct net_device_stats *epic_get_stats(struct device *dev)
 {
-	struct epic_private *tp = (struct epic_private *)dev->priv;
-	int ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
 
 	if (dev->start) {
 		/* Update the error counts. */
-		tp->stats.rx_missed_errors += inb(ioaddr + MPCNT);
-		tp->stats.rx_frame_errors += inb(ioaddr + ALICNT);
-		tp->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
+		ep->stats.rx_missed_errors += inb(ioaddr + MPCNT);
+		ep->stats.rx_frame_errors += inb(ioaddr + ALICNT);
+		ep->stats.rx_crc_errors += inb(ioaddr + CRCCNT);
 	}
 
-	return &tp->stats;
+	return &ep->stats;
 }
 
 /* Set or clear the multicast filter for this adaptor.
    Note that we only use exclusion around actually queueing the
-   new frame, not around filling tp->setup_frame.  This is non-deterministic
+   new frame, not around filling ep->setup_frame.  This is non-deterministic
    when re-entered but still correct. */
 
 /* The little-endian AUTODIN II ethernet CRC calculation.
@@ -1149,21 +1233,17 @@
 }
 
 
-#ifdef NEW_MULTICAST
 static void set_rx_mode(struct device *dev)
-#else
-static void set_rx_mode(struct device *dev, int num_addrs, void *addrs);
-#endif
 {
-	int ioaddr = dev->base_addr;
-	struct epic_private *tp = (struct epic_private *)dev->priv;
+	long ioaddr = dev->base_addr;
+	struct epic_private *ep = (struct epic_private *)dev->priv;
 	unsigned char mc_filter[8];		 /* Multicast hash filter */
 	int i;
 
 	if (dev->flags & IFF_PROMISC) {			/* Set promiscuous. */
 		outl(0x002C, ioaddr + RxCtrl);
 		/* Unconditionally log net taps. */
-		printk("%s: Promiscuous mode enabled.\n", dev->name);
+		printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
 		memset(mc_filter, 0xff, sizeof(mc_filter));
 	} else if ((dev->mc_count > 0)  ||  (dev->flags & IFF_ALLMULTI)) {
 		/* There is apparently a chip bug, so the multicast filter
@@ -1184,45 +1264,176 @@
 					mc_filter);
 	}
 	/* ToDo: perhaps we need to stop the Tx and Rx process here? */
-	if (memcmp(mc_filter, tp->mc_filter, sizeof(mc_filter))) {
+	if (memcmp(mc_filter, ep->mc_filter, sizeof(mc_filter))) {
 		for (i = 0; i < 4; i++)
 			outw(((u16 *)mc_filter)[i], ioaddr + MC0 + i*4);
-		memcpy(tp->mc_filter, mc_filter, sizeof(mc_filter));
+		memcpy(ep->mc_filter, mc_filter, sizeof(mc_filter));
 	}
 	return;
 }
+
+static int mii_ioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+	long ioaddr = dev->base_addr;
+	u16 *data = (u16 *)&rq->ifr_data;
+
+	switch(cmd) {
+	case SIOCDEVPRIVATE:		/* Get the address of the PHY in use. */
+		data[0] = ((struct epic_private *)dev->priv)->phys[0] & 0x1f;
+		/* Fall Through */
+	case SIOCDEVPRIVATE+1:		/* Read the specified MII register. */
+		if (! dev->start) {
+			outl(0x0200, ioaddr + GENCTL);
+			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+		}
+		data[3] = mdio_read(ioaddr, data[0] & 0x1f, data[1] & 0x1f);
+		if (! dev->start) {
+#ifdef notdef
+			outl(0x0008, ioaddr + GENCTL);
+			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+#endif
+		}
+		return 0;
+	case SIOCDEVPRIVATE+2:		/* Write the specified MII register */
+		if (!suser())
+			return -EPERM;
+		if (! dev->start) {
+			outl(0x0200, ioaddr + GENCTL);
+			outl((inl(ioaddr + NVCTL) & ~0x003C) | 0x4800, ioaddr + NVCTL);
+		}
+		mdio_write(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2]);
+		if (! dev->start) {
+#ifdef notdef
+			outl(0x0008, ioaddr + GENCTL);
+			outl((inl(ioaddr + NVCTL) & ~0x483C) | 0x0000, ioaddr + NVCTL);
+#endif
+		}
+		return 0;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 
-#ifdef MODULE
+#ifdef CARDBUS
 
-/* An additional parameter that may be passed in... */
-static int debug = -1;
+#include <pcmcia/driver_ops.h>
 
-int
-init_module(void)
+static dev_node_t *epic_attach(dev_locator_t *loc)
+{
+	struct device *dev;
+	u16 dev_id;
+	u32 io;
+	u8 bus, devfn, irq;
+
+	if (loc->bus != LOC_PCI) return NULL;
+	bus = loc->b.pci.bus; devfn = loc->b.pci.devfn;
+	printk(KERN_DEBUG "epic_attach(bus %d, function %d)\n", bus, devfn);
+	pcibios_read_config_dword(bus, devfn, PCI_BASE_ADDRESS_0, &io);
+	pcibios_read_config_byte(bus, devfn, PCI_INTERRUPT_LINE, &irq);
+	pcibios_read_config_word(bus, devfn, PCI_DEVICE_ID, &dev_id);
+	io &= ~3;
+	if (io == 0 || irq == 0) {
+		printk(KERN_ERR "The EPIC/C CardBus Ethernet interface was not "
+			   "assigned an %s.\n" KERN_ERR "  It will not be activated.\n",
+			   io == 0 ? "I/O address" : "IRQ");
+		return NULL;
+	}
+	dev = epic_probe1(bus, devfn, NULL, io, irq, 2, -1);
+	if (dev) {
+		dev_node_t *node = kmalloc(sizeof(dev_node_t), GFP_KERNEL);
+		strcpy(node->dev_name, dev->name);
+		node->major = node->minor = 0;
+		node->next = NULL;
+		MOD_INC_USE_COUNT;
+		return node;
+	}
+	return NULL;
+}
+
+static void epic_suspend(dev_node_t *node)
+{
+	struct device **devp, **next;
+	printk(KERN_INFO "epic_suspend(%s)\n", node->dev_name);
+	for (devp = &root_epic_dev; *devp; devp = next) {
+		next = &((struct epic_private *)(*devp)->priv)->next_module;
+		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	}
+	if (*devp) {
+		long ioaddr = (*devp)->base_addr;
+		epic_pause(*devp);
+		/* Put the chip into low-power mode. */
+		outl(0x0008, ioaddr + GENCTL);
+	}
+}
+static void epic_resume(dev_node_t *node)
+{
+	struct device **devp, **next;
+	printk(KERN_INFO "epic_resume(%s)\n", node->dev_name);
+	for (devp = &root_epic_dev; *devp; devp = next) {
+		next = &((struct epic_private *)(*devp)->priv)->next_module;
+		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	}
+	if (*devp) {
+		epic_restart(*devp);
+	}
+}
+static void epic_detach(dev_node_t *node)
 {
-	int cards_found;
+	struct device **devp, **next;
+	printk(KERN_INFO "epic_detach(%s)\n", node->dev_name);
+	for (devp = &root_epic_dev; *devp; devp = next) {
+		next = &((struct epic_private *)(*devp)->priv)->next_module;
+		if (strcmp((*devp)->name, node->dev_name) == 0) break;
+	}
+	if (*devp) {
+		unregister_netdev(*devp);
+		kfree(*devp);
+		*devp = *next;
+		kfree(node);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+struct driver_operations epic_ops = {
+	"epic_cb", epic_attach, epic_suspend, epic_resume, epic_detach
+};
 
-	if (debug >= 0)
-		epic_debug = debug;
+#endif  /* Cardbus support */
 
-	root_epic_dev = NULL;
-	cards_found = epic100_probe(0);
+
+#ifdef MODULE
 
-	return cards_found ? 0 : -ENODEV;
+int init_module(void)
+{
+	if (epic_debug)
+		printk(KERN_INFO "%s", version);
+
+#ifdef CARDBUS
+	register_driver(&epic_ops);
+	return 0;
+#else
+	return epic100_probe(0);
+#endif
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 	struct device *next_dev;
 
+#ifdef CARDBUS
+	unregister_driver(&epic_ops);
+#endif
+
 	/* No need to check MOD_IN_USE, as sys_delete_module() checks. */
 	while (root_epic_dev) {
-		next_dev = ((struct epic_private *)root_epic_dev->priv)->next_module;
+		struct epic_private *ep = (struct epic_private *)root_epic_dev->priv;
+		next_dev = ep->next_module;
 		unregister_netdev(root_epic_dev);
 		release_region(root_epic_dev->base_addr, EPIC_TOTAL_SIZE);
 		kfree(root_epic_dev);
 		root_epic_dev = next_dev;
+		kfree(ep);
 	}
 }
 
@@ -1230,7 +1441,8 @@
 
 /*
  * Local variables:
- *  compile-command: "gcc -DMODULE -DMODVERSIONS -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c"
+ *  compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
+ *  cardbus-compile-command: "gcc -DCARDBUS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c epic100.c -o epic_cb.o -I/usr/src/pcmcia-cs-3.0.5/include/"
  *  c-indent-level: 4
  *  c-basic-offset: 4
  *  tab-width: 4
diff -u --recursive --new-file v2.1.131/linux/drivers/net/es3210.c linux/drivers/net/es3210.c
--- v2.1.131/linux/drivers/net/es3210.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/net/es3210.c	Wed Dec 16 13:35:49 1998
@@ -439,7 +439,6 @@
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
 			release_region(dev->base_addr, ES_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/hamradio/scc.c linux/drivers/net/hamradio/scc.c
--- v2.1.131/linux/drivers/net/hamradio/scc.c	Thu Feb 12 20:56:08 1998
+++ linux/drivers/net/hamradio/scc.c	Fri Dec 18 13:57:21 1998
@@ -1,4 +1,4 @@
-#define RCS_ID "$Id: scc.c,v 1.73 1998/01/29 17:38:51 jreuter Exp jreuter $"
+#define RCS_ID "$Id: scc.c,v 1.75 1998/11/04 15:15:01 jreuter Exp jreuter $"
 
 #define VERSION "3.0"
 #define BANNER  "Z8530 SCC driver version "VERSION".dl1bke (experimental) by DL1BKE\n"
@@ -60,22 +60,22 @@
    Incomplete history of z8530drv:
    -------------------------------
 
-   940913	- started to write the driver, rescued most of my own
-		  code (and Hans Alblas' memory buffer pool concept) from 
-		  an earlier project "sccdrv" which was initiated by 
-		  Guido ten Dolle. Not much of the old driver survived, 
-		  though. The first version I put my hands on was sccdrv1.3
-		  from August 1993. The memory buffer pool concept
-		  appeared in an unauthorized sccdrv version (1.5) from
-		  August 1994.
+   1994-09-13	started to write the driver, rescued most of my own
+		code (and Hans Alblas' memory buffer pool concept) from 
+		an earlier project "sccdrv" which was initiated by 
+		Guido ten Dolle. Not much of the old driver survived, 
+		though. The first version I put my hands on was sccdrv1.3
+		from August 1993. The memory buffer pool concept
+		appeared in an unauthorized sccdrv version (1.5) from
+		August 1994.
 
-   950131	- changed copyright notice to GPL without limitations.
+   1995-01-31	changed copyright notice to GPL without limitations.
    
      .
      .	<SNIP>
      .
    		  
-   961005	- New semester, new driver... 
+   1996-10-05	New semester, new driver... 
 
    		  * KISS TNC emulator removed (TTY driver)
    		  * Source moved to drivers/net/
@@ -88,12 +88,22 @@
    		  The move to version number 3.0 reflects theses changes.
    		  You can use 'kissbridge' if you need a KISS TNC emulator.
 
-   961213	- Fixed for Linux networking changes. (G4KLX)
-   970108	- Fixed the remaining problems.
-   970402	- Hopefully fixed the problems with the new *_timer()
-   		  routines, added calibration code.
-   971012	- Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO
-   980129	- Small fix to avoid lock-up on initialization
+   1996-12-13	Fixed for Linux networking changes. (G4KLX)
+   1997-01-08	Fixed the remaining problems.
+   1997-04-02	Hopefully fixed the problems with the new *_timer()
+   		routines, added calibration code.
+   1997-10-12	Made SCC_DELAY a CONFIG option, added CONFIG_SCC_TRXECHO
+   1998-01-29	Small fix to avoid lock-up on initialization
+   1998-09-29	Fixed the "grouping" bugs, tx_inhibit works again,
+   		using dev->tx_queue_len now instead of MAXQUEUE now.
+   1998-10-21	Postponed the spinlock changes, would need a lot of
+   		testing I currently don't have the time to. Softdcd doesn't
+   		work.
+   1998-11-04	Softdcd does not work correctly in DPLL mode, in fact it 
+   		never did. The DPLL locks on noise, the SYNC unit sees
+   		flags that aren't... Restarting the DPLL does not help
+   		either, it resynchronizes too slow and the first received
+   		frame gets lost.
 
    Thanks to all who contributed to this driver with ideas and bug
    reports!
@@ -119,22 +129,22 @@
    Joerg Reuter	ampr-net: dl1bke@db0pra.ampr.org
 		AX-25   : DL1BKE @ DB0ACH.#NRW.DEU.EU
 		Internet: jreuter@poboxes.com
-		www     : http://www.rat.de/jr
+		www     : http://poboxes.com/jreuter/
 */
 
 /* ----------------------------------------------------------------------- */
 
 #undef  SCC_LDELAY	1	/* slow it even a bit more down */
-#undef  DONT_CHECK		/* don't look if the SCCs you specified are available */
+#undef  SCC_DONT_CHECK		/* don't look if the SCCs you specified are available */
 
-#define MAXSCC          4       /* number of max. supported chips */
-#define BUFSIZE         384     /* must not exceed 4096 */
-#define MAXQUEUE	8	/* number of buffers we queue ourself */
-#undef  DISABLE_ALL_INTS	/* use cli()/sti() in ISR instead of */
+#define SCC_MAXCHIPS	4       /* number of max. supported chips */
+#define SCC_BUFSIZE	384     /* must not exceed 4096 */
+#undef  SCC_DISABLE_ALL_INTS	/* use cli()/sti() in ISR instead of */
 				/* enable_irq()/disable_irq()        */
 #undef	SCC_DEBUG
 
-#define DEFAULT_CLOCK	4915200 /* default pclock if nothing is specified */
+#define SCC_DEFAULT_CLOCK	4915200 
+				/* default pclock if nothing is specified */
 
 /* ----------------------------------------------------------------------- */
 
@@ -214,13 +224,13 @@
 
 static struct irqflags { unsigned char used : 1; } Ivec[16];
 	
-static struct scc_channel SCC_Info[2 * MAXSCC];	/* information per channel */
+static struct scc_channel SCC_Info[2 * SCC_MAXCHIPS];	/* information per channel */
 
 static struct scc_ctrl {
 	io_port chan_A;
 	io_port chan_B;
 	int irq;
-} SCC_ctrl[MAXSCC+1];
+} SCC_ctrl[SCC_MAXCHIPS+1];
 
 static unsigned char Driver_Initialized = 0;
 static int Nchips = 0;
@@ -236,7 +246,7 @@
 
 /* These provide interrupt save 2-step access to the Z8530 registers */
 
-extern __inline__ unsigned char InReg(io_port port, unsigned char reg)
+static inline unsigned char InReg(io_port port, unsigned char reg)
 {
 	unsigned long flags;
 	unsigned char r;
@@ -256,7 +266,7 @@
 	return r;
 }
 
-extern __inline__ void OutReg(io_port port, unsigned char reg, unsigned char val)
+static inline void OutReg(io_port port, unsigned char reg, unsigned char val)
 {
 	unsigned long flags;
 	
@@ -272,31 +282,31 @@
 	restore_flags(flags);
 }
 
-extern __inline__ void wr(struct scc_channel *scc, unsigned char reg,
+static inline void wr(struct scc_channel *scc, unsigned char reg,
 	unsigned char val)
 {
 	OutReg(scc->ctrl, reg, (scc->wreg[reg] = val));
 }
 
-extern __inline__ void or(struct scc_channel *scc, unsigned char reg, unsigned char val)
+static inline void or(struct scc_channel *scc, unsigned char reg, unsigned char val)
 {
 	OutReg(scc->ctrl, reg, (scc->wreg[reg] |= val));
 }
 
-extern __inline__ void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
+static inline void cl(struct scc_channel *scc, unsigned char reg, unsigned char val)
 {
 	OutReg(scc->ctrl, reg, (scc->wreg[reg] &= ~val));
 }
 
-#ifdef DISABLE_ALL_INTS
-extern __inline__ void scc_cli(int irq)
+#ifdef SCC_DISABLE_ALL_INTS
+static inline void scc_cli(int irq)
 { cli(); }
-extern __inline__ void scc_sti(int irq)
+static inline void scc_sti(int irq)
 { sti(); }
 #else
-static __inline__ void scc_cli(int irq)
+static inline void scc_cli(int irq)
 { disable_irq(irq); }
-static __inline__ void scc_sti(int irq)
+static inline void scc_sti(int irq)
 { enable_irq(irq); }
 #endif
 
@@ -305,17 +315,17 @@
 /* ******************************************************************** */
 
 
-extern __inline__ void scc_lock_dev(struct scc_channel *scc)
+static inline void scc_lock_dev(struct scc_channel *scc)
 {
 	scc->dev->tbusy = 1;
 }
 
-extern __inline__ void scc_unlock_dev(struct scc_channel *scc)
+static inline void scc_unlock_dev(struct scc_channel *scc)
 {
 	scc->dev->tbusy = 0;
 }
 
-extern __inline__ void scc_discard_buffers(struct scc_channel *scc)
+static inline void scc_discard_buffers(struct scc_channel *scc)
 {
 	unsigned long flags;
 	
@@ -343,7 +353,7 @@
 
 /* ----> subroutines for the interrupt handlers <---- */
 
-extern __inline__ void scc_notify(struct scc_channel *scc, int event)
+static inline void scc_notify(struct scc_channel *scc, int event)
 {
 	struct sk_buff *skb;
 	char *bp;
@@ -362,7 +372,7 @@
 		scc->stat.nospace++;
 }
 
-extern __inline__ void flush_rx_FIFO(struct scc_channel *scc)
+static inline void flush_rx_FIFO(struct scc_channel *scc)
 {
 	int k;
 	
@@ -377,12 +387,18 @@
 	}
 }
 
+static void start_hunt(struct scc_channel *scc)
+{
+	if ((scc->modem.clocksrc != CLK_EXTERNAL))
+		OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
+	or(scc,R3,ENT_HM|RxENABLE);  /* enable the receiver, hunt mode */
+}
 
 /* ----> four different interrupt handlers for Tx, Rx, changing of	*/
 /*       DCD/CTS and Rx/Tx errors					*/
 
 /* Transmitter interrupt handler */
-extern __inline__ void scc_txint(struct scc_channel *scc)
+static inline void scc_txint(struct scc_channel *scc)
 {
 	struct sk_buff *skb;
 
@@ -446,7 +462,7 @@
 
 
 /* External/Status interrupt handler */
-extern __inline__ void scc_exint(struct scc_channel *scc)
+static inline void scc_exint(struct scc_channel *scc)
 {
 	unsigned char status,changes,chg_and_stat;
 
@@ -461,35 +477,39 @@
 	if (chg_and_stat & BRK_ABRT)		/* Received an ABORT */
 		flush_rx_FIFO(scc);
 
+	/* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
+
+	if ((changes & SYNC_HUNT) && scc->kiss.softdcd)
+	{
+		if (status & SYNC_HUNT)
+		{
+			scc->dcd = 0;
+			flush_rx_FIFO(scc);
+			if ((scc->modem.clocksrc != CLK_EXTERNAL))
+				OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
+		} else {
+			scc->dcd = 1;
+		}
+
+		scc_notify(scc, scc->dcd? HWEV_DCD_OFF:HWEV_DCD_ON);
+	}
 
 	/* DCD: on = start to receive packet, off = ABORT condition */
 	/* (a successfully received packet generates a special condition int) */
 	
-	if(changes & DCD)                       /* DCD input changed state */
+	if((changes & DCD) && !scc->kiss.softdcd) /* DCD input changed state */
 	{
 		if(status & DCD)                /* DCD is now ON */
 		{
-			if (scc->modem.clocksrc != CLK_EXTERNAL)
-				OutReg(scc->ctrl,R14,SEARCH|scc->wreg[R14]); /* DPLL: enter search mode */
-				
-			or(scc,R3,ENT_HM|RxENABLE); /* enable the receiver, hunt mode */
+			start_hunt(scc);
+			scc->dcd = 1;
 		} else {                        /* DCD is now OFF */
 			cl(scc,R3,ENT_HM|RxENABLE); /* disable the receiver */
 			flush_rx_FIFO(scc);
+			scc->dcd = 0;
 		}
 		
-		if (!scc->kiss.softdcd)
-			scc_notify(scc, (status & DCD)? HWEV_DCD_ON:HWEV_DCD_OFF);
-	}
-	
-	/* HUNT: software DCD; on = waiting for SYNC, off = receiving frame */
-	
-	if (changes & SYNC_HUNT)
-	{
-		if (scc->kiss.softdcd)
-			scc_notify(scc, (status & SYNC_HUNT)? HWEV_DCD_OFF:HWEV_DCD_ON);
-		else
-			cl(scc,R15,SYNCIE);	/* oops, we were too lazy to disable this? */
+		scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
 	}
 
 #ifdef notdef
@@ -527,7 +547,7 @@
 
 
 /* Receiver interrupt handler */
-extern __inline__ void scc_rxint(struct scc_channel *scc)
+static inline void scc_rxint(struct scc_channel *scc)
 {
 	struct sk_buff *skb;
 
@@ -575,7 +595,7 @@
 
 
 /* Receive Special Condition interrupt handler */
-extern __inline__ void scc_spint(struct scc_channel *scc)
+static inline void scc_spint(struct scc_channel *scc)
 {
 	unsigned char status;
 	struct sk_buff *skb;
@@ -646,8 +666,6 @@
 	struct scc_ctrl *ctrl;
 	int k;
 	
-	scc_cli(irq);
-
 	if (Vector_Latch)
 	{
 	    	for(k=0; k < SCC_IRQTIMEOUT; k++)
@@ -665,7 +683,6 @@
 
 			OutReg(scc->ctrl,R0,RES_H_IUS);              /* Reset Highest IUS */
 		}  
-		scc_sti(irq);
 
 		if (k == SCC_IRQTIMEOUT)
 			printk(KERN_WARNING "z8530drv: endless loop in scc_isr()?\n");
@@ -718,8 +735,6 @@
 		} else
 			ctrl++;
 	}
-	
-	scc_sti(irq);
 }
 
 
@@ -731,7 +746,7 @@
 
 /* ----> set SCC channel speed <---- */
 
-extern __inline__ void set_brg(struct scc_channel *scc, unsigned int tc)
+static inline void set_brg(struct scc_channel *scc, unsigned int tc)
 {
 	cl(scc,R14,BRENABL);		/* disable baudrate generator */
 	wr(scc,R12,tc & 255);		/* brg rate LOW */
@@ -739,7 +754,7 @@
 	or(scc,R14,BRENABL);		/* enable baudrate generator */
 }
 
-extern __inline__ void set_speed(struct scc_channel *scc)
+static inline void set_speed(struct scc_channel *scc)
 {
 	disable_irq(scc->irq);
 
@@ -752,7 +767,7 @@
 
 /* ----> initialize a SCC channel <---- */
 
-extern __inline__ void init_brg(struct scc_channel *scc)
+static inline void init_brg(struct scc_channel *scc)
 {
 	wr(scc, R14, BRSRC);				/* BRG source = PCLK */
 	OutReg(scc->ctrl, R14, SSBR|scc->wreg[R14]);	/* DPLL source = BRG */
@@ -875,19 +890,15 @@
 		wr(scc,R7,AUTOEOM);
 	}
 
-	if((InReg(scc->ctrl,R0)) & DCD)		/* DCD is now ON */
+	if(scc->kiss.softdcd || (InReg(scc->ctrl,R0) & DCD))
+						/* DCD is now ON */
 	{
-		if (scc->modem.clocksrc != CLK_EXTERNAL)
-			or(scc,R14, SEARCH);
-			
-		or(scc,R3,ENT_HM|RxENABLE);	/* enable the receiver, hunt mode */
+		start_hunt(scc);
 	}
 	
 	/* enable ABORT, DCD & SYNC/HUNT interrupts */
 
-	wr(scc,R15, BRKIE|TxUIE|DCDIE);
-	if (scc->kiss.softdcd)
-		or(scc,R15, SYNCIE);
+	wr(scc,R15, BRKIE|TxUIE|(scc->kiss.softdcd? SYNCIE:DCDIE));
 
 	Outb(scc->ctrl,RES_EXT_INT);	/* reset ext/status interrupts */
 	Outb(scc->ctrl,RES_EXT_INT);	/* must be done twice */
@@ -940,14 +951,21 @@
 		{
 #ifdef CONFIG_SCC_TRXECHO
 			cl(scc, R3, RxENABLE|ENT_HM);	/* switch off receiver */
-			cl(scc, R15, DCDIE);		/* No DCD changes, please */
+			cl(scc, R15, DCDIE|SYNCIE);	/* No DCD changes, please */
 #endif
 			set_brg(scc, time_const);	/* reprogram baudrate generator */
 
 			/* DPLL -> Rx clk, BRG -> Tx CLK, TRxC mode output, TRxC = BRG */
 			wr(scc, R11, RCDPLL|TCBR|TRxCOI|TRxCBR);
 			
-			or(scc,R5,RTS|TxENAB);		/* set the RTS line and enable TX */
+			/* By popular demand: tx_inhibit */
+			if (scc->kiss.tx_inhibit)
+			{
+				or(scc,R5, TxENAB);
+				scc->wreg[R5] |= RTS;
+			} else {
+				or(scc,R5,RTS|TxENAB);	/* set the RTS line and enable TX */
+			}
 		} else {
 			cl(scc,R5,RTS|TxENAB);
 			
@@ -955,10 +973,14 @@
 			
 			/* DPLL -> Rx clk, DPLL -> Tx CLK, TRxC mode output, TRxC = DPLL */
 			wr(scc, R11, RCDPLL|TCDPLL|TRxCOI|TRxCDP);
-#ifdef CONFIG_SCC_TRXECHO
-			or(scc,R3,RxENABLE|ENT_HM);
-			or(scc,R15, DCDIE);
+
+#ifndef CONFIG_SCC_TRXECHO
+			if (scc->kiss.softdcd)
 #endif
+			{
+				or(scc,R15, scc->kiss.softdcd? SYNCIE:DCDIE);
+				start_hunt(scc);
+			}
 		}
 	} else {
 		if (tx)
@@ -967,22 +989,30 @@
 			if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
 			{
 				cl(scc, R3, RxENABLE);
-				cl(scc, R15, DCDIE);
+				cl(scc, R15, DCDIE|SYNCIE);
 			}
 #endif
 				
-				
-			or(scc,R5,RTS|TxENAB);		/* enable tx */
+			if (scc->kiss.tx_inhibit)
+			{
+				or(scc,R5, TxENAB);
+				scc->wreg[R5] |= RTS;
+			} else {	
+				or(scc,R5,RTS|TxENAB);	/* enable tx */
+			}
 		} else {
 			cl(scc,R5,RTS|TxENAB);		/* disable tx */
 
-#ifdef CONFIG_SCC_TRXECHO
-			if (scc->kiss.fulldup == KISS_DUPLEX_HALF)
+			if ((scc->kiss.fulldup == KISS_DUPLEX_HALF) &&
+#ifndef CONFIG_SCC_TRXECHO
+			    scc->kiss.softdcd)
+#else
+			    1)
+#endif
 			{
-				or(scc, R3, RxENABLE|ENT_HM);
-				or(scc, R15, DCDIE);
+				or(scc, R15, scc->kiss.softdcd? SYNCIE:DCDIE);
+				start_hunt(scc);
 			}
-#endif
 		}
 	}
 
@@ -1088,7 +1118,7 @@
 
 static unsigned char Rand = 17;
 
-extern __inline__ int is_grouped(struct scc_channel *scc)
+static inline int is_grouped(struct scc_channel *scc)
 {
 	int k;
 	struct scc_channel *scc2;
@@ -1109,7 +1139,7 @@
 			if ( (grp1 & TXGROUP) && (scc2->wreg[R5] & RTS) )
 				return 1;
 			
-			if ( (grp1 & RXGROUP) && (scc2->status & DCD) )
+			if ( (grp1 & RXGROUP) && scc2->dcd )
 				return 1;
 		}
 	}
@@ -1144,7 +1174,7 @@
 	{
 		Rand = Rand * 17 + 31;
 		
-		if ( (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD))  || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
+		if (scc->dcd || (scc->kiss.persist) < Rand || (scc->kiss.group && is_grouped(scc)) )
 		{
 			scc_start_defer(scc);
 			scc_start_tx_timer(scc, t_dwait, scc->kiss.slottime);
@@ -1317,8 +1347,6 @@
 
 static unsigned int scc_set_param(struct scc_channel *scc, unsigned int cmd, unsigned int arg)
 {
-	int dcd;
-
 	switch (cmd)
 	{
 		case PARAM_TXDELAY:	scc->kiss.txdelay=arg;		break;
@@ -1338,9 +1366,14 @@
 		case PARAM_SOFTDCD:	
 			scc->kiss.softdcd=arg;
 			if (arg)
+			{
 				or(scc, R15, SYNCIE);
-			else
+				cl(scc, R15, DCDIE);
+				start_hunt(scc);
+			} else {
+				or(scc, R15, DCDIE);
 				cl(scc, R15, SYNCIE);
+			}
 			break;
 				
 		case PARAM_SPEED:
@@ -1369,8 +1402,7 @@
 			break;
 			
 		case PARAM_HWEVENT:
-			dcd = (scc->kiss.softdcd? !(scc->status & SYNC_HUNT):(scc->status & DCD));
-			scc_notify(scc, dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
+			scc_notify(scc, scc->dcd? HWEV_DCD_ON:HWEV_DCD_OFF);
 			break;
 
 		default:		return -EINVAL;
@@ -1449,9 +1481,10 @@
 
 	scc->tx_wdog.data = (unsigned long) scc;
 	scc->tx_wdog.function = scc_stop_calibrate;
-	scc->tx_wdog.expires = jiffies + HZ*scc->kiss.maxkeyup;
+	scc->tx_wdog.expires = jiffies + HZ*duration;
 	add_timer(&scc->tx_wdog);
-	
+
+	/* This doesn't seem to work. Why not? */	
 	wr(scc, R6, 0);
 	wr(scc, R7, pattern);
 
@@ -1680,6 +1713,7 @@
 	skb->dev      = scc->dev;
 	skb->protocol = htons(ETH_P_AX25);
 	skb->mac.raw  = skb->data;
+	skb->pkt_type = PACKET_HOST;
 	
 	netif_rx(skb);
 	return;
@@ -1722,7 +1756,7 @@
 	save_flags(flags);
 	cli();
 	
-	if (skb_queue_len(&scc->tx_queue) >= MAXQUEUE-1)
+	if (skb_queue_len(&scc->tx_queue) > scc->dev->tx_queue_len)
 	{
 		struct sk_buff *skb_del;
 		skb_del = __skb_dequeue(&scc->tx_queue);
@@ -1791,7 +1825,7 @@
 			if (!suser()) return -EPERM;
 			if (!arg) return -EFAULT;
 
-			if (Nchips >= MAXSCC) 
+			if (Nchips >= SCC_MAXCHIPS) 
 				return -EINVAL;
 
 			if (copy_from_user(&hwcfg, arg, sizeof(hwcfg)))
@@ -1811,14 +1845,15 @@
 				Vector_Latch = hwcfg.vector_latch;
 
 			if (hwcfg.clock == 0)
-				hwcfg.clock = DEFAULT_CLOCK;
+				hwcfg.clock = SCC_DEFAULT_CLOCK;
 
-#ifndef DONT_CHECK
+#ifndef SCC_DONT_CHECK
 			disable_irq(hwcfg.irq);
 
 			check_region(scc->ctrl, 1);
 			Outb(hwcfg.ctrl_a, 0);
-			udelay(5);
+			OutReg(hwcfg.ctrl_a, R9, FHWRES);
+			udelay(100);
 			OutReg(hwcfg.ctrl_a,R13,0x55);		/* is this chip really there? */
 			udelay(5);
 
@@ -1853,7 +1888,7 @@
 				SCC_Info[2*Nchips+chan].option = hwcfg.option;
 				SCC_Info[2*Nchips+chan].enhanced = hwcfg.escc;
 
-#ifdef DONT_CHECK
+#ifdef SCC_DONT_CHECK
 				printk(KERN_INFO "%s: data port = 0x%3.3x  control port = 0x%3.3x\n",
 					device_name, 
 					SCC_Info[2*Nchips+chan].data, 
@@ -1903,7 +1938,7 @@
 			if (!suser()) return -EPERM;
 			if (!arg) return -EINVAL;
 			
-			scc->stat.bufsize   = BUFSIZE;
+			scc->stat.bufsize   = SCC_BUFSIZE;
 
 			if (copy_from_user(&scc->modem, arg, sizeof(struct scc_modem)))
 				return -EINVAL;
@@ -1980,7 +2015,7 @@
 		
 		case SIOCSCCCAL:
 			if (!suser()) return -EPERM;
-			if (!arg || copy_from_user(&cal, arg, sizeof(cal)))
+			if (!arg || copy_from_user(&cal, arg, sizeof(cal)) || cal.time == 0)
 				return -EINVAL;
 
 			scc_start_calibrate(scc, cal.time, cal.pattern);
@@ -2169,7 +2204,7 @@
 	
 	/* pre-init channel information */
 	
-	for (chip = 0; chip < MAXSCC; chip++)
+	for (chip = 0; chip < SCC_MAXCHIPS; chip++)
 	{
 		memset((char *) &SCC_Info[2*chip  ], 0, sizeof(struct scc_channel));
 		memset((char *) &SCC_Info[2*chip+1], 0, sizeof(struct scc_channel));
diff -u --recursive --new-file v2.1.131/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- v2.1.131/linux/drivers/net/hp-plus.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/net/hp-plus.c	Wed Dec 16 13:35:49 1998
@@ -474,7 +474,6 @@
 			void *priv = dev->priv;
 			/* NB: hpp_close() handles free_irq */
 			release_region(ioaddr, HP_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/hp.c linux/drivers/net/hp.c
--- v2.1.131/linux/drivers/net/hp.c	Tue Jun  9 11:57:29 1998
+++ linux/drivers/net/hp.c	Wed Dec 16 13:35:49 1998
@@ -445,7 +445,6 @@
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
 			release_region(ioaddr, HP_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ibmtr.c linux/drivers/net/ibmtr.c
--- v2.1.131/linux/drivers/net/ibmtr.c	Thu Nov 12 16:21:19 1998
+++ linux/drivers/net/ibmtr.c	Fri Dec 18 09:36:05 1998
@@ -1230,7 +1230,7 @@
 {
 	struct tok_info *ti;
 	short PIOaddr;
-	int i;
+	unsigned long i;
 	PIOaddr = dev->base_addr;
 	ti=(struct tok_info *) dev->priv;
 
@@ -1252,7 +1252,7 @@
 #endif
 
 	outb(0, PIOaddr+ADAPTRESET);
-	for (i=jiffies+TR_RESET_INTERVAL; jiffies<=i;); /* wait 50ms */
+	for (i=jiffies+TR_RESET_INTERVAL; time_before_eq(jiffies, i);); /* wait 50ms */
 	outb(0,PIOaddr+ADAPTRESETREL);
 
 #if !TR_NEWFORMAT
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.1.131/linux/drivers/net/irda/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/Config.in	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,16 @@
+mainmenu_option next_comment
+comment 'Infrared-port device drivers'
+
+dep_tristate 'IrTTY (uses serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
+if [ "$CONFIG_IRTTY_SIR" != "n" ]; then
+  comment '   Dongle support' 
+  bool '   Serial dongle support' CONFIG_DONGLE
+  if [ "$CONFIG_DONGLE" != "n" ]; then
+    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
+  fi
+fi
+dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
+dep_tristate '  Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+endmenu
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.1.131/linux/drivers/net/irda/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/Makefile	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,72 @@
+# File: drivers/irda/Makefile
+#
+# Makefile for the Linux IrDA infrared port device drivers.
+#
+
+SUB_DIRS     := 
+MOD_SUB_DIRS := $(SUB_DIRS)
+ALL_SUB_DIRS := $(SUB_DIRS)
+
+L_TARGET := irda_drivers.a
+L_OBJS   := 
+M_OBJS   :=
+MOD_LIST_NAME := IRDA_MODULES
+
+ifeq ($(CONFIG_IRTTY_SIR),y)
+L_OBJS += irtty.o
+else
+  ifeq ($(CONFIG_IRTTY_SIR),m)
+  M_OBJS += irtty.o
+  endif
+endif
+
+ifeq ($(CONFIG_NSC_FIR),y)
+L_OBJS += pc87108.o
+else
+  ifeq ($(CONFIG_NSC_FIR),m)
+  M_OBJS += pc87108.o
+  endif
+endif
+
+ifeq ($(CONFIG_WINBOND_FIR),y)
+L_OBJS += w83977af_ir.o
+else
+  ifeq ($(CONFIG_WINBOND_FIR),m)
+  M_OBJS += w83977af_ir.o
+  endif
+endif
+
+ifeq ($(CONFIG_ESI_DONGLE),y)
+L_OBJS += esi.o
+else
+  ifeq ($(CONFIG_ESI_DONGLE),m)
+  M_OBJS += esi.o
+  endif
+endif
+
+ifeq ($(CONFIG_TEKRAM_DONGLE),y)
+L_OBJS += tekram.o
+else
+  ifeq ($(CONFIG_TEKRAM_DONGLE),m)
+  M_OBJS += tekram.o
+  endif
+endif
+
+ifeq ($(CONFIG_ACTISYS_DONGLE),y)
+L_OBJS += actisys.o
+else
+  ifeq ($(CONFIG_ACTISYS_DONGLE),m)
+  M_OBJS += actisys.o
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
+
+clean:
+	rm -f core *.o *.a *.s
+
+
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.1.131/linux/drivers/net/irda/actisys.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/actisys.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,314 @@
+/*********************************************************************
+ *                
+ * Filename:      actisys.c
+ * Version:       0.3
+ * 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 Dec 14 11:50:32 1998
+ * 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/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 actisys_reset( struct irda_device *dev, int unused);
+static void actisys_open( struct irda_device *idev, int type);
+static void actisys_close( struct irda_device *dev);
+static void actisys_change_speed( struct irda_device *dev, int baudrate);
+static void actisys_reset( struct irda_device *dev, int unused);
+static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos);
+
+/* These are the baudrates supported */
+static int baud_rates[] = { 9600, 19200, 57600, 115200, 38400};
+
+static struct dongle dongle = {
+	ACTISYS_DONGLE,
+	actisys_open,
+	actisys_close,
+	actisys_reset,
+	actisys_change_speed,
+	actisys_init_qos,
+};
+
+__initfunc(void actisys_init(void))
+{
+	irtty_register_dongle(&dongle);
+}
+
+void actisys_cleanup(void)
+{
+	irtty_unregister_dongle(&dongle);
+}
+
+static void actisys_open( struct irda_device *idev, int type)
+{
+	strcat( idev->name, " <-> actisys");
+
+        idev->io.dongle_id = type;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void actisys_close( struct irda_device *dev)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * 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 :-(
+ */
+static void actisys_change_speed( struct irda_device *idev, int baudrate)
+{
+        struct irtty_cb *self;
+        struct tty_struct *tty;
+        int arg = 0;
+        struct termios old_termios;
+	int cflag;
+        int current_baudrate;
+        int index = 0;
+	mm_segment_t fs;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	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;);
+
+	current_baudrate = idev->qos.baud_rate.value;
+
+	/* Find the correct baudrate index for the currently used baudrate */
+	while ( current_baudrate != baud_rates[index])
+		index++;
+
+        DEBUG( 0, __FUNCTION__ "(), index=%d\n", index);
+
+	if ( !self->tty)
+		return;
+
+	tty = self->tty;
+
+	/* Cycle through avaiable baudrates until we reach the correct one */
+        while ( current_baudrate != baudrate) {	
+                DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n",
+                       baud_rates[index]);
+		DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
+		
+		/* Set DTR, clear RTS */
+		arg = TIOCM_DTR;
+		
+		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);
+		
+		/* Wait at a few ms */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(2);
+
+		/* Set DTR, Set RTS */
+                arg = TIOCM_DTR | TIOCM_RTS;
+
+		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);
+		
+		/* Wait at a few ms again */
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout( 2);
+
+                /* Go to next baudrate */
+		if ( idev->io.dongle_id == ACTISYS_DONGLE)
+                        index = (index+1) % 4; /* IR-220L */
+		else
+                        index = (index+1) % 5; /* IR-220L+ */
+
+                current_baudrate = baud_rates[index];
+        }
+	DEBUG( 0, __FUNCTION__ "(), current baudrate = %d\n", 
+                  baud_rates[index]);
+
+	/* Now change the speed of the serial port */
+	old_termios = *(tty->termios);
+	cflag = tty->termios->c_cflag;
+
+	cflag &= ~CBAUD;
+
+        switch ( baudrate) {
+        case 9600:
+        default:
+		cflag |= B9600;
+		break;
+	case 19200:
+		cflag |= B19200;
+		break;
+	case 38400:
+		cflag |= B38400;
+		break;
+	case 57600:
+		cflag |= B57600;
+		break;
+	case 115200:
+		cflag |= B115200;
+		break;
+	}
+
+	tty->termios->c_cflag = cflag;
+
+	DEBUG( 0, __FUNCTION__ "(), Setting the speed of the serial port\n");
+	tty->driver.set_termios( tty, &old_termios);
+}
+
+/*
+ * Function actisys_reset (dev)
+ *
+ *      Reset the Actisys type dongle. Warning, this function must only be
+ *      called with a process context!
+ *
+ *    	1. Clear DTR for a few ms.
+ *
+ */
+static void actisys_reset( struct irda_device *idev, int unused)
+{
+	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;);
+	
+	self = (struct irtty_cb *) idev->priv;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+	tty = self->tty;
+	if ( !tty)
+		return;
+
+	DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
+	arg = TIOCM_RTS;
+
+	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);
+
+	/* Sleep 10-20 ms*/
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(2);
+	
+	DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
+	arg = TIOCM_RTS | TIOCM_DTR;
+	
+	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);
+
+	idev->qos.baud_rate.value = 9600;
+}
+
+/*
+ * Function actisys_init_qos (qos)
+ *
+ *    Initialize QoS capabilities
+ *
+ */
+static void actisys_init_qos( struct irda_device *idev, struct qos_info *qos)
+{
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+
+	/* Remove support for 38400 if this is not a 220L+ dongle */
+	if ( idev->io.dongle_id == ACTISYS_DONGLE)
+		qos->baud_rate.bits &= ~IR_38400;
+		
+	qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+		
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Actisys module
+ *
+ */
+int init_module(void)
+{
+	actisys_init();
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Actisys module
+ *
+ */
+void cleanup_module(void)
+{
+	actisys_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.1.131/linux/drivers/net/irda/esi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/esi.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,195 @@
+/*********************************************************************
+ *                
+ * Filename:      esi.c
+ * Version:       1.0
+ * Description:   Driver for the Extended Systems JetEye PC
+ * Status:        Experimental.
+ * Author:        Thomas Davis, <ratbert@radiks.net>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Mon Dec 14 11:48:22 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:	  esi.c
+ *
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>,
+ *     Copyright (c) 1998, Dag Brattli,  <dagb@cs.uit.no>
+ *     All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <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 esi_open( struct irda_device *idev, int type);
+static void esi_close( struct irda_device *driver);
+static void esi_change_speed( struct irda_device *idev, int baud);
+static void esi_reset( struct irda_device *idev, int unused);
+static void esi_qos_init( struct irda_device *idev, struct qos_info *qos);
+
+static struct dongle dongle = {
+	ESI_DONGLE,
+	esi_open,
+	esi_close,
+	esi_reset,
+	esi_change_speed,
+	esi_qos_init,
+};
+
+__initfunc(void esi_init(void))
+{
+	irtty_register_dongle( &dongle);
+}
+
+void esi_cleanup(void)
+{
+	irtty_unregister_dongle( &dongle);
+}
+
+static void esi_open( struct irda_device *idev, int type)
+{
+	strcat( idev->name, " <-> esi");
+
+	idev->io.dongle_id = type;
+
+	MOD_INC_USE_COUNT;
+}
+
+static void esi_close( struct irda_device *driver)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function esi_change_speed (tty, baud)
+ *
+ *    Set the speed for the Extended Systems JetEye PC ESI-9680 type dongle
+ *
+ */
+static void esi_change_speed( struct irda_device *idev, int baud)
+{
+	struct irtty_cb *self;
+	struct tty_struct *tty;
+	int arg = 0;
+        struct termios old_termios;
+	int cflag;
+	mm_segment_t fs;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	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 (baud) {
+	case 19200:
+		cflag |= B19200;
+		arg = TIOCM_DTR;
+		break;
+	case 115200:
+		cflag |= B115200;
+		arg = TIOCM_RTS | TIOCM_DTR;
+		break;
+	case 9600:
+	default:
+		cflag |= B9600;
+		arg = TIOCM_RTS;
+		break;
+	}
+		
+	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, "error setting ESI speed!\n");
+	}
+	set_fs(fs);
+}
+
+static void esi_reset( struct irda_device *idev, int unused)
+{
+	/* Empty */
+}
+
+/*
+ * Function esi_qos_init (qos)
+ *
+ *    Init QoS capabilities for the dongle
+ *
+ */
+static void esi_qos_init( struct irda_device *idev, struct qos_info *qos)
+{
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_115200;
+}
+
+#ifdef MODULE
+		
+/*
+ * Function init_module (void)
+ *
+ *    Initialize ESI module
+ *
+ */
+int init_module(void)
+{
+	esi_init();
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup ESI module
+ *
+ */
+void cleanup_module(void)
+{
+        esi_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.1.131/linux/drivers/net/irda/irport.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/irport.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,361 @@
+/*********************************************************************
+ *		  
+ * Filename:	  irport.c
+ * Version:	  0.1
+ * Description:   Serial driver for IrDA. The functions in this file
+ *                may be used by FIR drivers, but this file knows
+ *                nothing about FIR drivers!!!
+ * Status:	  Experimental.
+ * Author:	  Dag Brattli <dagb@cs.uit.no>
+ * Created at:	  Sun Aug  3 13:49:59 1997
+ * Modified at:   Sat May 23 23:15:20 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:	  serial.c by Linus Torvalds 
+ *		  serial_serial.c by Aage Kvalnes <aage@cs.uit.no>
+ * 
+ *     Copyright (c) 1997,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/types.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <linux/errno.h>
+
+#include <linux/skbuff.h>
+#include <linux/serial_reg.h>
+
+#include "irda.h"
+#include "ircompat.h"
+#include "irport.h"
+#include "timer.h"
+#include "crc.h"
+#include "wrapper.h"
+#include "irlap_frame.h"
+
+#define IO_EXTENT	8
+
+static void irport_write_wakeup( struct irda_device *idev);
+static int irport_write( int iobase, int fifo_size, __u8 *buf, int len);
+static void irport_receive( struct irda_device *idev);
+
+/*
+ * Function irport_open (void)
+ *
+ *    Start IO port 
+ *
+ */
+int irport_open( int iobase)
+{
+	/* Initialize UART */
+	outb_p( UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
+	outb_p(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), 
+	       iobase+UART_MCR);
+	
+	/* Turn on interrups */
+	outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), 
+	       iobase+UART_IER); 
+	
+	return 0;
+}
+
+/*
+ * Function irport_cleanup ()
+ *
+ *    Stop IO port
+ *
+ */
+void irport_close( int iobase) 
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	/* Reset UART */
+	outb_p( 0, iobase+UART_MCR);
+
+	/* Turn off interrupts */
+	outb_p( 0, iobase+UART_IER); 
+}
+
+/*
+ * Function irport_change_speed (idev, speed)
+ *
+ *    Set speed of port to specified baudrate
+ *
+ */
+void irport_change_speed( int iobase, int speed) 
+{
+	int fcr;    /* FIFO control reg */
+	int lcr;    /* Line control reg */
+	int divisor;
+
+	DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
+
+	/* Turn off interrupts */
+	outb_p( 0, iobase+UART_IER); 
+
+	divisor = SPEED_MAX/speed;
+	
+	fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_14;
+        
+	/* IrDA ports use 8N1 */
+	lcr = UART_LCR_WLEN8;
+	
+	outb_p( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
+	outb_p( divisor & 0xff,      iobase+UART_DLL); /* Set speed	*/
+	outb_p( divisor >> 8,	     iobase+UART_DLM);
+	outb_p( lcr,		     iobase+UART_LCR); /* Set 8N1	*/
+	outb_p( fcr,		     iobase+UART_FCR); /* Enable FIFO's */
+
+	/* Turn on interrups */
+	outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), 
+	       iobase+UART_IER); 
+}
+
+/*
+ * Function irport_interrupt (irq, dev_id, regs)
+ *
+ *    
+ */
+void irport_interrupt( int irq, void *dev_id, struct pt_regs *regs) 
+{
+	struct irda_device *idev = (struct irda_device *) dev_id;
+
+	int iobase, status;
+	int iir;
+
+	DEBUG( 4, __FUNCTION__ "(), irq %d\n", irq);
+
+	if ( !idev) {
+		printk( KERN_WARNING __FUNCTION__ 
+			"() irq %d for unknown device.\n", irq);
+		return;
+	}
+
+	iobase = idev->io.iobase;
+	iir    = inb( iobase + UART_IIR);
+
+	do {
+		status = inb( iobase+UART_LSR);
+		
+		if ( status & UART_LSR_DR) {
+	       		/* Receive interrupt */
+			irport_receive( idev);
+		}
+		if ( status & UART_LSR_THRE) {
+	       		/* Transmitter ready for data */
+			irport_write_wakeup( idev);
+		}
+	} while ( !(inb( iobase+UART_IIR) & UART_IIR_NO_INT));
+}
+
+/*
+ * Function irport_write_wakeup (tty)
+ *
+ *    Called by the driver when there's room for more data.  If we have
+ *    more packets to send, we send them here.
+ *
+ */
+static void irport_write_wakeup( struct irda_device *idev)
+{
+	int actual = 0, count;
+	
+	DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
+	
+	/* 
+	 *  First make sure we're connected. 
+	 */
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	/*
+	 *  Finished with frame?
+	 */
+	if ( idev->tx.ptr == idev->tx.len)  {
+
+		/* 
+		 *  Now serial buffer is almost free & we can start 
+		 *  transmission of another packet 
+		 */
+		DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+
+		idev->netdev.tbusy = 0; /* Unlock */
+		idev->stats.tx_packets++;
+
+		/* Schedule network layer, so we can get some more frames */
+		mark_bh( NET_BH);
+		return;
+	}
+	/*
+	 *  Write data left in transmit buffer
+	 */
+	count = idev->tx.len - idev->tx.ptr;
+	actual = irport_write( idev->io.iobase, idev->io.fifo_size, 
+			       idev->tx.head, count);
+	idev->tx.ptr += actual;
+	idev->tx.head += actual;
+}
+
+/*
+ * Function irport_write (driver)
+ *
+ *    
+ *
+ */
+static int irport_write( int iobase, int fifo_size, __u8 *buf, int len)
+{
+	int actual = 0;
+
+	if (!(inb_p( iobase+UART_LSR) & UART_LSR_THRE)) {
+		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
+		return -1;
+	}
+        
+	/* Fill FIFO with current frame */
+	while (( fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb( buf[actual], iobase+UART_TX);
+
+		actual++;
+	}
+        
+	DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+	       fifo_size, actual, len);
+
+	return actual;
+}
+
+/*
+ * Function irport_xmit (void)
+ *
+ *    Transmits the current frame until FIFO is full, then
+ *    waits until the next transmitt interrupt, and continues until the
+ *    frame is transmited.
+ */
+int irport_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+	struct irda_device *idev;
+	int xbofs;
+	int actual;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( dev != NULL, return -1;);
+
+	if ( dev->tbusy) {
+		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+		
+		return -EBUSY;
+	}
+	
+	idev = (struct irda_device *)  dev->priv;
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	if ( skb == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), skb==NULL\n");
+#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
+		dev_tint(dev); 
+#endif
+		return 0;
+	}
+
+	/* Lock transmit buffer */
+	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+	
+        /*  
+	 *  Transfer skb to tx_buff while wrapping, stuffing and making CRC 
+	 */
+	idev->tx.len = async_wrap_skb( skb, idev->tx.buff, idev->tx.buffsize);
+
+	actual = irport_write( idev->io.iobase, idev->io.fifo_size, 
+			       idev->tx.buff, idev->tx.len);
+
+	idev->tx.ptr = actual;
+	idev->tx.head = idev->tx.buff + actual;
+
+	IS_SKB( skb, return 0;);
+	FREE_SKB_MAGIC( skb);
+	DEV_KFREE_SKB( skb, FREE_WRITE);
+
+	return 0;
+}
+        
+/*
+ * Function irport_receive (void)
+ *
+ *    Receive one frame from the infrared port
+ *
+ */
+static void irport_receive( struct irda_device *idev) 
+{
+	__u8 byte = 0x00;
+	int iobase;
+
+	if ( !idev)
+		return;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	iobase = idev->io.iobase;
+
+	if ( idev->rx.len == 0) {
+		idev->rx.head = idev->rx.buff;
+	}
+
+	/* 
+	 *  Receive all characters in FIFO 
+	 */
+	do {
+		byte = inb_p( iobase+UART_RX);
+		async_unwrap_char( idev, byte);
+		
+	} while ( inb_p( iobase+UART_LSR) & UART_LSR_DR);	
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    
+ *
+ */
+/* void cleanup_module(void) */
+/* { */
+/* 	DEBUG( 3, "IrPORT: cleanup_module!\n"); */
+/* 	irport_cleanup(irport_drv); */
+/* } */
+
+/*
+ * Function init_module (void)
+ *
+ *    
+ *
+ */
+/* int init_module(void) */
+/* { */
+/* 	if (irport_init() < 0) { */
+/* 		cleanup_module(); */
+/* 		return 1; */
+/* 	} */
+/* 	return(0); */
+/* } */
+
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.1.131/linux/drivers/net/irda/irtty.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/irtty.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,748 @@
+/*********************************************************************
+ *                
+ * Filename:      irtty.c
+ * Version:       1.0
+ * 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 Dec 14 20:09:42 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       slip.c by Laurence Culhane,   <loz@holmes.demon.co.uk>
+ *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ * 
+ *     Copyright (c) 1998 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/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <asm/segment.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irtty.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irlap.h>
+#include <net/irda/timer.h>
+#include <net/irda/irda_device.h>
+#include <linux/kmod.h>
+
+static hashbin_t *irtty = NULL;
+static hashbin_t *dongles = NULL;
+
+static struct tty_ldisc irda_ldisc;
+
+static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev);
+static void irtty_wait_until_sent( struct irda_device *driver);
+static int irtty_is_receiving( struct irda_device *idev);
+static int irtty_net_init( struct device *dev);
+static int irtty_net_open(struct device *dev);
+static int irtty_net_close(struct device *dev);
+
+static int  irtty_open( struct tty_struct *tty);
+static void irtty_close( struct tty_struct *tty);
+static int  irtty_ioctl( struct tty_struct *, void *, int, void *);
+static int  irtty_receive_room( struct tty_struct *tty);
+static void irtty_change_speed( struct irda_device *dev, int baud);
+static void irtty_write_wakeup( struct tty_struct *tty);
+
+static void irtty_receive_buf( struct tty_struct *, const unsigned char *, 
+			       char *, int);
+char *driver_name = "irtty";
+
+__initfunc(int irtty_init(void))
+{
+	int status;
+	
+	irtty = hashbin_new( HB_LOCAL);
+	if ( irtty == NULL) {
+		printk( KERN_WARNING "IrDA: Can't allocate irtty hashbin!\n");
+		return -ENOMEM;
+	}
+
+	dongles = hashbin_new( HB_LOCAL);
+	if ( dongles == NULL) {
+		printk( KERN_WARNING 
+			"IrDA: Can't allocate dongles hashbin!\n");
+		return -ENOMEM;
+	}
+
+	/* Fill in our line protocol discipline, and register it */
+	memset( &irda_ldisc, 0, sizeof( irda_ldisc));
+
+	irda_ldisc.magic = TTY_LDISC_MAGIC;
+ 	irda_ldisc.name  = "irda";
+	irda_ldisc.flags = 0;
+	irda_ldisc.open  = irtty_open;
+	irda_ldisc.close = irtty_close;
+	irda_ldisc.read  = NULL;
+	irda_ldisc.write = NULL;
+	irda_ldisc.ioctl = (int (*)(struct tty_struct *, struct file *,
+				    unsigned int, unsigned long)) irtty_ioctl;
+ 	irda_ldisc.poll  = NULL;
+	irda_ldisc.receive_buf  = irtty_receive_buf;
+	irda_ldisc.receive_room = irtty_receive_room;
+	irda_ldisc.write_wakeup = irtty_write_wakeup;
+	
+	if (( status = tty_register_ldisc( N_IRDA, &irda_ldisc)) != 0)  {
+		printk( KERN_ERR 
+			"IrDA: can't register line discipline (err = %d)\n", 
+			status);
+	}
+	
+	return status;
+}
+
+/* 
+ *  Function irtty_cleanup ( )
+ *
+ *    Called when the irda module is removed. Here we remove all instances
+ *    of the driver, and the master array.
+ */
+#ifdef MODULE
+static void irtty_cleanup(void) 
+{
+	int ret;
+	
+	/*
+	 *  Unregister tty line-discipline
+	 */
+	if (( ret = tty_register_ldisc( N_IRDA, NULL))) {
+		printk( KERN_ERR 
+			"IrTTY: can't unregister line discipline (err = %d)\n",
+ 			ret);
+	}
+
+	/*
+	 *  The TTY should care of deallocating the instances by using the
+	 *  callback to irtty_close(), therefore we do give any deallocation
+	 *  function to hashbin_destroy().
+	 */
+	hashbin_delete( irtty, NULL);
+	hashbin_delete( dongles, NULL);
+}
+#endif /* MODULE */
+
+/* 
+ *  Function irtty_open(tty)
+ *
+ *    This function is called by the TTY module when the IrDA line
+ *    discipline is called for.  Because we are sure the tty line exists,
+ *    we only have to link it to a free IrDA channel.  
+ */
+static int irtty_open( struct tty_struct *tty) 
+{
+	struct irtty_cb *self;
+	char name[16];
+	
+	ASSERT( tty != NULL, return -EEXIST;);
+
+	/* First make sure we're not already connected. */
+	self = (struct irtty_cb *) tty->disc_data;
+	if ( self != NULL && self->magic == IRTTY_MAGIC)
+		return -EEXIST;
+	
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc( sizeof(struct irtty_cb), GFP_KERNEL);
+	if ( self == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset( self, 0, sizeof(struct irtty_cb));
+	
+	self->tty = tty;
+	tty->disc_data = self;
+
+	/* Give self a name */
+	sprintf( name, "%s%d", tty->driver.name,
+		 MINOR(tty->device) - tty->driver.minor_start +
+		 tty->driver.name_base);
+
+	/* hashbin_insert( irtty, (QUEUE*) self, 0, self->name); */
+	hashbin_insert( irtty, (QUEUE*) self, (int) self, NULL);
+
+	if (tty->driver.flush_buffer) {
+		tty->driver.flush_buffer(tty);
+	}
+
+	if (tty->ldisc.flush_buffer) {
+		tty->ldisc.flush_buffer(tty);
+	}
+	
+	self->magic = IRTTY_MAGIC;
+
+	/*
+	 *  Initialize driver
+	 */
+	/* self->idev.flags |= SIR_MODE | IO_PIO; */
+	self->idev.rx_buff.state = OUTSIDE_FRAME;
+
+	/* 
+	 *  Initialize QoS capabilities, we fill in all the stuff that
+	 *  we support. Be careful not to place any restrictions on values
+	 *  that are not device dependent (such as link disconnect time) so
+	 *  this parameter can be set by IrLAP (or the user) instead. DB
+	 */
+	irda_init_max_qos_capabilies( &self->idev.qos);
+
+	/* The only value we must override it the baudrate */
+	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200;
+	irda_qos_bits_to_value( &self->idev.qos);
+
+	/* Specify which buffer allocation policy we need */
+	self->idev.rx_buff.flags = GFP_KERNEL;
+	self->idev.tx_buff.flags = GFP_KERNEL;
+
+	/* Specify how much memory we want */
+	self->idev.rx_buff.truesize = 4000; 
+	self->idev.tx_buff.truesize = 4000;
+
+	/* Initialize callbacks */
+	self->idev.change_speed    = irtty_change_speed;
+ 	self->idev.is_receiving    = irtty_is_receiving;
+	/* self->idev.is_tbusy        = irtty_is_tbusy; */
+	self->idev.wait_until_sent = irtty_wait_until_sent;
+
+	/* Override the network functions we need to use */
+	self->idev.netdev.init            = irtty_net_init;
+	self->idev.netdev.hard_start_xmit = irtty_hard_xmit;
+	self->idev.netdev.open            = irtty_net_open;
+	self->idev.netdev.stop            = irtty_net_close;
+
+	/* Open the IrDA device */
+	irda_device_open( &self->idev, name, self);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/* 
+ *  Function irtty_close ( tty)
+ *
+ *    Close down a IrDA channel. This means flushing out any pending queues,
+ *    and then restoring the TTY line discipline to what it was before it got
+ *    hooked to IrDA (which usually is TTY again).  
+ */
+static void irtty_close( struct tty_struct *tty) 
+{
+	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+	
+	/* First make sure we're connected. */
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+	/* We are not using any dongle anymore! */
+	if ( self->dongle_q)
+		self->dongle_q->dongle->close( &self->idev);
+
+	/* Remove driver */
+	irda_device_close( &self->idev);
+
+	/* Stop tty */
+	tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+	tty->disc_data = 0;
+
+	self->tty = NULL;
+	self->magic = 0;
+	
+	/* hashbin_remove( irtty, 0, self->name); */
+	self = hashbin_remove( irtty, (int) self, NULL);
+	
+	if ( self != NULL)
+		kfree( self);
+
+ 	MOD_DEC_USE_COUNT;
+
+	DEBUG( 4, "IrTTY: close() -->\n");
+}
+
+/* 
+ *  Function irtty_change_speed ( self, baud)
+ *
+ *    Change the speed of the serial port. The driver layer must check that
+ *    all transmission has finished using the irtty_wait_until_sent() 
+ *    function.
+ */
+static void irtty_change_speed( struct irda_device *idev, int baud) 
+{
+        struct termios old_termios;
+	struct irtty_cb *self;
+	int cflag;
+
+	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;);
+
+	old_termios = *(self->tty->termios);
+	cflag = self->tty->termios->c_cflag;
+
+	cflag &= ~CBAUD;
+
+	DEBUG( 4, __FUNCTION__ "(), Setting speed to %d\n", baud);
+
+	switch( baud) {
+	case 1200:
+		cflag |= B1200;
+		break;
+	case 2400:
+		cflag |= B2400;
+		break;
+	case 4800:
+		cflag |= B4800;
+		break;
+	case 19200:
+		cflag |= B19200;
+		break;
+	case 38400:
+		cflag |= B38400;
+		break;
+	case 57600:
+		cflag |= B57600;
+		break;
+	case 115200:
+		cflag |= B115200;
+		break;
+	case 9600:
+	default:
+		cflag |= B9600;
+		break;
+	}	
+
+	self->tty->termios->c_cflag = cflag;
+	self->tty->driver.set_termios( self->tty, &old_termios);
+}
+
+/*
+ * Function irtty_init_dongle (self, type)
+ *
+ *    Initialize attached dongle. Warning, must be called with a process
+ *    context!
+ */
+static void irtty_init_dongle( struct irtty_cb *self, int type)
+{
+	struct dongle_q *node;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+#ifdef CONFIG_KMOD
+	/* Try to load the module needed */
+	switch( type) {
+	case ESI_DONGLE:
+		DEBUG( 0, __FUNCTION__ "(), ESI dongle!\n");
+		request_module( "esi");
+		break;
+	case TEKRAM_DONGLE:
+		DEBUG( 0, __FUNCTION__ "(), Tekram dongle!\n");
+		request_module( "tekram");
+		break;
+	case ACTISYS_DONGLE:
+		DEBUG( 0, __FUNCTION__ "(), ACTiSYS dongle!\n");
+		request_module( "actisys");
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown dongle type!\n");
+		return;
+		break;
+	}
+#endif /* CONFIG_KMOD */
+
+	node = hashbin_find( dongles, type, NULL);
+	if ( !node) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to find requested dongle\n");
+		return;
+	}
+	self->dongle_q = node;
+
+	/* Use this change speed function instead of the default */
+	self->idev.change_speed = node->dongle->change_speed;
+
+	/*
+	 * Now initialize the dongle!
+	 */
+	node->dongle->open( &self->idev, type);
+	node->dongle->qos_init( &self->idev, &self->idev.qos);
+	
+	/* Reset dongle */
+	node->dongle->reset( &self->idev, 0);
+
+	/* Set to default baudrate */
+	node->dongle->change_speed( &self->idev, 9600);
+}
+
+/*
+ * Function irtty_ioctl (tty, file, cmd, arg)
+ *
+ *     The Swiss army knife of system calls :-)
+ *
+ */
+static int irtty_ioctl( struct tty_struct *tty, void *file, int cmd, 
+			void *arg) 
+{
+	struct irtty_cb *self;
+	int err = 0;
+	int size = _IOC_SIZE(cmd);
+
+	self = (struct irtty_cb *) tty->disc_data;
+
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == IRTTY_MAGIC, return -EBADR;);
+
+	if ( _IOC_DIR(cmd) & _IOC_READ)
+		err = verify_area( VERIFY_WRITE, (void *) arg, size);
+	else if ( _IOC_DIR(cmd) & _IOC_WRITE)
+		err = verify_area( VERIFY_READ, (void *) arg, size);
+	if ( err)
+		return err;
+	
+	switch(cmd) {
+	case TCGETS:
+	case TCGETA:
+		return n_tty_ioctl( tty, (struct file *) file, cmd, 
+				    (unsigned long) arg);
+		break;
+	case IRTTY_IOCTDONGLE:
+		/* Initialize dongle */
+		irtty_init_dongle( self, (int) arg);
+		break;
+	default:
+		return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+/* 
+ *  Function irtty_receive_buf( tty, cp, count)
+ *
+ *    Handle the 'receiver data ready' interrupt.  This function is called
+ *    by the 'tty_io' module in the kernel when a block of IrDA data has
+ *    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) 
+{
+	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+	
+	/* Read the characters out of the buffer */
+ 	while (count--) {
+		/* 
+		 *  Characters received with a parity error, etc?
+		 */
+ 		if (fp && *fp++) { 
+			DEBUG( 0, "Framing or parity error!\n");
+			irda_device_set_media_busy( &self->idev, TRUE);
+			/* sl->rx_errors++; */
+ 			cp++;
+ 			continue;
+ 		}
+		/*
+		 *  Unwrap and destuff one byte
+		 */
+		async_unwrap_char( &self->idev, *cp++);
+		/* self->rx_over_errors++; */
+
+	}
+}
+
+/*
+ * Function irtty_hard_xmit (skb, dev)
+ *
+ *    Transmit skb
+ *
+ */
+static int irtty_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+	struct irtty_cb *self;
+	struct irda_device *idev;
+	int actual = 0;
+
+	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;);
+	
+	self = (struct irtty_cb *) idev->priv;
+
+	ASSERT( self != NULL, return 0;);
+	ASSERT( self->magic == IRTTY_MAGIC, return 0;);
+
+	/* Lock transmit buffer */
+	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+		return 0;
+
+        /*  
+	 *  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); 
+
+	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);
+
+	idev->tx_buff.offset = actual;
+	idev->tx_buff.head = idev->tx_buff.data + actual;
+#if 0
+	/* 
+	 *  Did we transmit the whole frame? Commented out for now since
+	 *  I must check if this optimalization really works. DB.
+	 */
+ 	if (( idev->tx.count - idev->tx.ptr) <= 0) {
+ 		DEBUG( 4, "irtty_xmit_buf: finished with frame!\n");
+ 		self->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+ 		irda_unlock( &self->tbusy);
+ 	}
+#endif
+
+	dev_kfree_skb( skb);
+
+	return 0;
+}
+
+/*
+ * Function irtty_receive_room (tty)
+ *
+ *    Used by the TTY to find out how much data we can receive at a time
+ * 
+*/
+static int irtty_receive_room( struct tty_struct *tty) 
+{
+	return 65536;  /* We can handle an infinite amount of data. :-) */
+}
+
+/*
+ * Function irtty_write_wakeup (tty)
+ *
+ *    Called by the driver when there's room for more data.  If we have
+ *    more packets to send, we send them here.
+ *
+ */
+static void irtty_write_wakeup( struct tty_struct *tty) 
+{
+	int actual = 0, count;
+	struct irtty_cb *self = (struct irtty_cb *) tty->disc_data;
+	struct irda_device *idev;
+	
+	/* 
+	 *  First make sure we're connected. 
+	 */
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+	idev = &self->idev;
+
+	/*
+	 *  Finished with frame?
+	 */
+	if ( idev->tx_buff.offset == idev->tx_buff.len)  {
+
+		/* 
+		 *  Now serial buffer is almost free & we can start 
+		 *  transmission of another packet 
+		 */
+		DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+
+		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+
+
+		idev->netdev.tbusy = 0; /* Unlock */
+		idev->stats.tx_packets++;
+
+		/* Tell network layer that we want more frames */
+		mark_bh( NET_BH);
+
+		return;
+	}
+	/*
+	 *  Write data left in transmit buffer
+	 */
+	count = idev->tx_buff.len - idev->tx_buff.offset;
+	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);
+}
+
+/*
+ * Function irtty_is_receiving (idev)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int irtty_is_receiving( struct irda_device *idev)
+{
+	return ( idev->rx_buff.state != OUTSIDE_FRAME);
+}
+
+/*
+ * Function irtty_change_speed_ready (idev)
+ *
+ *    Are we completely finished with transmitting frames so its possible
+ *    to change the speed of the serial port. Warning this function must
+ *    be called with a process context!
+ */
+static void irtty_wait_until_sent( struct irda_device *idev)
+{
+	struct irtty_cb *self = (struct irtty_cb *) idev->priv;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+	
+	DEBUG( 4, "Chars in buffer %d\n", 
+	       self->tty->driver.chars_in_buffer( self->tty));
+	
+	tty_wait_until_sent( self->tty, 0);
+}
+
+int irtty_register_dongle( struct dongle *dongle)
+{
+	struct dongle_q *new;
+	
+	/* Check if this compressor has been registred before */
+	if ( hashbin_find ( dongles, dongle->type, NULL)) {
+		DEBUG( 0, __FUNCTION__ "(), Dongle already registered\n");
+                return 0;
+        }
+	
+	/* Make new IrDA dongle */
+        new = (struct dongle_q *) kmalloc (sizeof (struct dongle_q), 
+					      GFP_KERNEL);
+        if (new == NULL) {
+                return 1;
+		
+        }
+	memset( new, 0, sizeof( struct dongle_q));
+        new->dongle = dongle;
+
+	/* Insert IrDA compressor into hashbin */
+	hashbin_insert( dongles, (QUEUE *) new, dongle->type, NULL);
+	
+        return 0;
+}
+
+void irtty_unregister_dongle( struct dongle *dongle)
+{
+	struct dongle_q *node;
+
+	node = hashbin_remove( dongles, dongle->type, NULL);
+	if ( !node) {
+		DEBUG( 0, __FUNCTION__ "(), dongle not found!\n");
+		return;
+	}
+	kfree( node);
+}
+
+static int irtty_net_init( struct device *dev)
+{
+	/* Set up to be a normal IrDA network device driver */
+	irda_device_setup( dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+
+static int irtty_net_open( struct device *dev)
+{
+	ASSERT( dev != NULL, return -1;);
+
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+static int irtty_net_close(struct device *dev)
+{
+	ASSERT( dev != NULL, return -1;);
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize IrTTY module
+ *
+ */
+int init_module(void)
+{
+	irtty_init();
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup IrTTY module
+ *
+ */
+void cleanup_module(void)
+{
+	irtty_cleanup();
+}
+
+#endif /* MODULE */
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.1.131/linux/drivers/net/irda/pc87108.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/pc87108.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,1500 @@
+/*********************************************************************
+ *                
+ * Filename:      pc87108.c
+ * Version:       0.8
+ * Description:   FIR/MIR driver for the NS PC87108 chip
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Nov  7 21:43:15 1998
+ * Modified at:   Mon Dec 14 11:40:24 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Notice that all functions that needs to access the chip in _any_
+ *     way, must save BSR register on entry, and restore it on exit. 
+ *     It is _very_ important to follow this policy!
+ *
+ *         __u8 bank;
+ *     
+ *         bank = inb( iobase+BSR);
+ *  
+ *         do_your_stuff_here();
+ *
+ *         outb( bank, iobase+BSR);
+ *
+ *    If you find bugs in this file, its very likely that the same bug
+ *    will also be in w83977af_ir.c since the implementations is quite
+ *    similar.
+ *     
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/pc87108.h>
+
+#define BROKEN_DONGLE_ID
+
+static char *driver_name = "pc87108";
+
+#define CHIP_IO_EXTENT 8
+
+static unsigned int io[]  = { 0x2f8, ~0, ~0, ~0 };
+static unsigned int io2[] = { 0x150, 0, 0, 0};
+static unsigned int irq[] = { 3, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0 };
+
+static struct pc87108 *dev_self[] = { NULL, NULL, NULL, NULL};
+
+static char *dongle_types[] = {
+	"Differential serial interface",
+	"Differential serial interface",
+	"Reserved",
+	"Reserved",
+	"Sharp RY5HD01",
+	"Reserved",
+	"Single-ended serial interface",
+	"Consumer-IR only",
+	"HP HSDL-2300, HP HSDL-3600/HSDL-3610",
+	"IBM31T1100 or Temic TFDS6000/TFDS6500",
+	"Reserved",
+	"Reserved",
+	"HP HSDL-1100/HSDL-2100",
+	"HP HSDL-1100/HSDL-2100"
+	"Supports SIR Mode only",
+	"No dongle connected",
+};
+
+/* Some prototypes */
+static int  pc87108_open( int i, unsigned int iobase, unsigned int board_addr, 
+			  unsigned int irq, unsigned int dma);
+static int  pc87108_close( struct irda_device *idev);
+static int  pc87108_probe( int iobase, int board_addr, int irq, int dma);
+static void pc87108_pio_receive( struct irda_device *idev);
+static int  pc87108_dma_receive( struct irda_device *idev); 
+static int  pc87108_dma_receive_complete(struct irda_device *idev, int iobase);
+static int  pc87108_hard_xmit( struct sk_buff *skb, struct device *dev);
+static int  pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
+static void pc87108_dma_write( struct irda_device *idev, int iobase);
+static void pc87108_change_speed( struct irda_device *idev, int baud);
+static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void pc87108_wait_until_sent( struct irda_device *idev);
+static int  pc87108_is_receiving( struct irda_device *idev);
+static int  pc87108_read_dongle_id ( int iobase);
+static void pc87108_init_dongle_interface ( int iobase, int dongle_id);
+
+static int  pc87108_net_init( struct device *dev);
+static int  pc87108_net_open( struct device *dev);
+static int  pc87108_net_close( struct device *dev);
+
+/*
+ * Function pc87108_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+__initfunc(int pc87108_init(void))
+{
+	int i;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+
+	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+		int ioaddr = io[i];
+		if (check_region(ioaddr, CHIP_IO_EXTENT))
+			continue;
+		if (pc87108_open( i, io[i], io2[i], irq[i], dma[i]) == 0)
+			return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Function pc87108_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void pc87108_cleanup(void)
+{
+	int i;
+
+        DEBUG( 4, __FUNCTION__ "()\n");
+
+	for ( i=0; i < 4; i++) {
+		if ( dev_self[i])
+			pc87108_close( &(dev_self[i]->idev));
+	}
+}
+#endif /* MODULE */
+
+/*
+ * Function pc87108_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+static int pc87108_open( int i, unsigned int iobase, unsigned int board_addr, 
+			 unsigned int irq, unsigned int dma)
+{
+	struct pc87108 *self;
+	struct irda_device *idev;
+	int ret;
+	int dongle_id;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	if (( dongle_id = pc87108_probe( iobase, board_addr, irq, dma)) == -1)
+		return -1;
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc( sizeof(struct pc87108), GFP_KERNEL);
+	if ( self == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset( self, 0, sizeof(struct pc87108));
+   
+	/* Need to store self somewhere */
+	dev_self[i] = self;
+
+	idev = &self->idev;
+
+	/* Initialize IO */
+	idev->io.iobase    = iobase;
+        idev->io.irq       = irq;
+        idev->io.io_ext    = CHIP_IO_EXTENT;
+        idev->io.dma       = dma;
+        idev->io.fifo_size = 32;
+
+	/* Lock the port that we need */
+	ret = check_region( idev->io.iobase, idev->io.io_ext);
+	if ( ret < 0) { 
+		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		       idev->io.iobase);
+		/* pc87108_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies( &idev->qos);
+	
+	/* The only value we must override it the baudrate */
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+	
+	idev->qos.min_turn_time.bits = 0x07;
+	irda_qos_bits_to_value( &idev->qos);
+	
+	/* Specify which buffer allocation policy we need */
+	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	idev->rx_buff.truesize = 14384; 
+	idev->tx_buff.truesize = 4000;
+	
+	/* Initialize callbacks */
+	idev->hard_xmit       = pc87108_hard_xmit;
+	idev->change_speed    = pc87108_change_speed;
+	idev->wait_until_sent = pc87108_wait_until_sent;
+	idev->is_receiving    = pc87108_is_receiving;
+     
+	/* Override the network functions we need to use */
+	idev->netdev.init            = pc87108_net_init;
+	idev->netdev.hard_start_xmit = pc87108_hard_xmit;
+	idev->netdev.open            = pc87108_net_open;
+	idev->netdev.stop            = pc87108_net_close;
+
+	idev->io.dongle_id = dongle_id;
+	pc87108_init_dongle_interface( iobase, dongle_id);
+
+	/* Open the IrDA device */
+	irda_device_open( idev, driver_name, self);
+	
+	return 0;
+}
+
+/*
+ * Function pc87108_close (idev)
+ *
+ *    Close driver instance
+ *
+ */
+static int pc87108_close( struct irda_device *idev)
+{
+	int iobase;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+        iobase = idev->io.iobase;
+
+	/* Release the PORT that this driver is using */
+	DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", 
+	       idev->io.iobase);
+	release_region( idev->io.iobase, idev->io.io_ext);
+
+	irda_device_close( idev);
+
+	return 0;
+}
+
+/*
+ * Function pc87108_probe (iobase, board_addr, irq, dma)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+static int pc87108_probe( int iobase, int board_addr, int irq, int dma) 
+{
+	int version;
+	__u8 temp=0;
+	int dongle_id;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Base Address and Interrupt Control Register BAIC */
+	outb(0, board_addr);
+	switch ( iobase) {
+	case 0x3E8: outb( 0x14, board_addr+1); break;
+	case 0x2E8: outb( 0x15, board_addr+1); break;
+	case 0x3F8: outb( 0x16, board_addr+1); break;
+	case 0x2F8: outb( 0x17, board_addr+1); break;
+	default:    DEBUG(0, __FUNCTION__ "(), invalid base_address");
+	}
+	
+	/* Control Signal Routing Register CSRT */
+	switch (irq) {
+	case 3:  temp = 0x01; break;
+	case 4:  temp = 0x02; break;
+	case 5:  temp = 0x03; break;
+	case 7:  temp = 0x04; break;
+	case 9:  temp = 0x05; break;
+	case 11: temp = 0x06; break;
+	case 15: temp = 0x07; break;
+	default: DEBUG( 0, __FUNCTION__ "(), invalid irq");
+	}
+	outb( 1, board_addr);
+
+	switch (dma) {	
+	case 0: outb( 0x08+temp, board_addr+1); break;
+	case 1: outb( 0x10+temp, board_addr+1); break;
+	case 3: outb( 0x18+temp, board_addr+1); break;
+	default: DEBUG( 0, __FUNCTION__ "(), invalid dma");
+	}
+
+	/* Mode Control Register MCTL */
+	outb( 2, board_addr);
+	outb( 0x03, board_addr+1);
+		
+	/* read the Module ID */
+	switch_bank( iobase, BANK3);
+	version =  inb( iobase+MID);
+	
+	/* should be 0x2? */
+	if (0x20 != (version & 0xf0))
+	{
+		DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
+		return -1;
+	}
+	
+	/* Switch to advanced mode */
+	switch_bank( iobase, BANK2);
+	outb( ECR1_EXT_SL, iobase+ECR1);
+	switch_bank( iobase, BANK0);
+
+	dongle_id = pc87108_read_dongle_id( iobase);
+	DEBUG( 0, __FUNCTION__ "(), Found dongle: %s\n", 
+	       dongle_types[ dongle_id]);
+	
+	/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
+	switch_bank( iobase, BANK0);	
+	outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	
+	/* Set FIFO size to 32 */
+	switch_bank( iobase, BANK2);
+	outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
+
+	/* IRCR2: FEND_MD is set */
+	switch_bank( iobase, BANK5);
+	outb( 0x2a, iobase+4);
+
+	/* Make sure that some defaults are OK */
+	switch_bank( iobase, BANK6);
+	outb( 0x20, iobase+0); /* Set 32 bits FIR CRC */
+	outb( 0x0a, iobase+1); /* Set MIR pulse width */
+	outb( 0x0d, iobase+2); /* Set SIR pulse width */
+	outb( 0x2a, iobase+4); /* Set beginning frag, and preamble length */
+
+	/* Receiver frame length */
+	switch_bank( iobase, BANK4);
+	outb( 4000 & 0xff, iobase+6);
+	outb(( 4000 >> 8) & 0x1f, iobase+7);
+
+	/* Transmitter frame length */
+	outb( 4000 & 0xff, iobase+4);
+	outb(( 4000 >> 8) & 0x1f, iobase+5);
+	
+	DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version);
+
+	/* Enable receive interrupts */
+	switch_bank( iobase, BANK0);
+	outb( IER_RXHDL_IE, iobase+IER);
+
+	return dongle_id;
+}
+
+/*
+ * Function pc87108_read_dongle_id (void)
+ *
+ * Try to read dongle indentification. This procedure needs to be executed
+ * once after power-on/reset. It also needs to be used whenever you suspect
+ * that the user may have plugged/unplugged the IrDA Dongle.
+ * 
+ */
+static int pc87108_read_dongle_id ( int iobase)
+{
+	int dongle_id;
+	__u8 bank;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	bank = inb( iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank( iobase, BANK7);
+	
+	/* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
+	outb( 0x00, iobase+7);
+	
+	/* ID0, 1, and 2 are pulled up/down very slowly */
+	udelay(50);
+	
+	/* IRCFG1: read the ID bits */
+	dongle_id = inb( iobase+4) & 0x0f;
+
+#ifdef BROKEN_DONGLE_ID
+	if ( dongle_id == 0x0a)
+		dongle_id = 0x09;
+#endif
+
+	/* Go back to  bank 0 before returning */
+	switch_bank( iobase, BANK0);
+
+	DEBUG( 0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
+
+	outb( bank, iobase+BSR);
+
+	return dongle_id;
+}
+
+/*
+ * Function pc87108_init_dongle_interface (iobase, dongle_id)
+ *
+ *     This function initializes the dongle for the transceiver that is
+ *     used. This procedure needs to be executed once after
+ *     power-on/reset. It also needs to be used whenever you suspect that
+ *     the dongle is changed. 
+ */
+static void pc87108_init_dongle_interface ( int iobase, int dongle_id)
+{
+	int bank;
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank( iobase, BANK7);
+	
+	/* IRCFG4: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x05: /* Reserved */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		outb_p( 0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		/* 
+		 * Set irsl0 as input, irsl[1-2] as output, and separate 
+		 * inputs are used for SIR and MIR/FIR 
+		 */
+		outb( 0x48, iobase+7); 
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		outb( 0x28, iobase+7); /* Set irsl[0-2] as output */
+		break;
+	case 0x0F: /* No dongle connected */
+		DEBUG( 0, __FUNCTION__ "(), %s\n",
+		       dongle_types[dongle_id]); 
+		DEBUG( 0, "***\n");
+
+		switch_bank( iobase, BANK0);
+		outb( 0x62, iobase+MCR);
+		break;
+	default: 
+		DEBUG( 0, __FUNCTION__ "(), invalid dongle_id %#x", dongle_id);
+	}
+	
+	/* IRCFG1: IRSL1 and 2 are set to IrDA mode */
+	outb( 0x00, iobase+4);
+
+	/* Restore bank register */
+	outb( bank, iobase+BSR);
+	
+} /* set_up_dongle_interface */
+
+/*
+ * Function pc87108_change_dongle_speed (iobase, speed, dongle_id)
+ *
+ *    Change speed of the attach dongle
+ *
+ */
+static void pc87108_change_dongle_speed( int iobase, int speed, int dongle_id)
+{
+	unsigned long flags;
+	__u8 bank;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	/* Select Bank 7 */
+	switch_bank( iobase, BANK7);
+	
+	/* IRCFG1: set according to dongle_id */
+	switch (dongle_id) {
+	case 0x00: /* same as */
+	case 0x01: /* Differential serial interface */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x02: /* same as */
+	case 0x03: /* Reserved */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x04: /* Sharp RY5HD01 */
+		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		       dongle_types[dongle_id]); 
+	case 0x05: /* Reserved */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x06: /* Single-ended serial interface */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x07: /* Consumer-IR only */
+		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
+		DEBUG( 0, __FUNCTION__ "(), %s not supported yet\n",
+		       dongle_types[dongle_id]); 
+	case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+		switch_bank( iobase, BANK7);
+		outb_p( 0x01, iobase+4);
+
+		if ( speed == 4000000) {
+			save_flags(flags);
+			cli();
+			outb( 0x81, iobase+4);
+			outb( 0x80, iobase+4);
+			restore_flags(flags);
+		}
+		else
+			outb_p( 0x00, iobase+4);
+		break;
+	case 0x0A: /* same as */
+	case 0x0B: /* Reserved */
+		DEBUG( 0, __FUNCTION__ "(), %s not defined by irda yet\n",
+		       dongle_types[dongle_id]); 
+		break;
+	case 0x0C: /* same as */
+	case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+		break;
+	case 0x0E: /* Supports SIR Mode only */
+		break;
+	case 0x0F: /* No dongle connected */
+		DEBUG( 0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+		       dongle_types[dongle_id]);
+
+		switch_bank( iobase, BANK0); 
+		outb( 0x62, iobase+MCR);
+		break;
+	default: 
+		DEBUG( 0, __FUNCTION__ "(), invalid data_rate\n");
+	}
+	/* Restore bank register */
+	outb( bank, iobase+BSR);
+}
+
+/*
+ * Function pc87108_change_speed (idev, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void pc87108_change_speed( struct irda_device *idev, int speed)
+{
+	__u8 mcr = MCR_SIR;
+	__u8 bank;
+	int iobase; 
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase;
+
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank( iobase, BANK0);
+	outb( 0, iobase+IER);
+
+	  /* Select Bank 2 */
+	switch_bank( iobase, BANK2);
+
+	outb( 0x00, iobase+BGDH);
+	switch ( speed) {
+	case 9600:   outb( 0x0c, iobase+BGDL); break;
+	case 19200:  outb( 0x06, iobase+BGDL); break;
+	case 37600:  outb( 0x03, iobase+BGDL); break;
+	case 57600:  outb( 0x02, iobase+BGDL); break;
+	case 115200: outb( 0x01, iobase+BGDL); break;
+	case 576000:
+		switch_bank( iobase, BANK5);
+		
+		/* IRCR2: MDRS is set */
+		outb( inb( iobase+4) | 0x04, iobase+4);
+	       
+		mcr = MCR_MIR;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		break;
+	case 1152000:
+		mcr = MCR_MIR;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		break;
+	case 4000000:
+		mcr = MCR_FIR;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		break;
+	default:
+		mcr = MCR_FIR;
+		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		break;
+	}
+
+	/* Set appropriate speed mode */
+	switch_bank(iobase, BANK0);
+	outb( mcr|MCR_TX_DFR, iobase+MCR);
+
+	/* Give some hits to the transceiver */
+	pc87108_change_dongle_speed( iobase, speed, idev->io.dongle_id);
+
+	/* Set FIFO threshold to TX17, RX16 */
+	switch_bank( iobase, BANK0);
+	outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	/* outb( 0xa7, iobase+FCR); */
+	
+	/* Set FIFO size to 32 */
+	switch_bank( iobase, BANK2);
+	outb( EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);	
+	
+	idev->netdev.tbusy = 0;
+	
+	/* Enable some interrupts so we can receive frames */
+	switch_bank( iobase, BANK0); 
+	if ( speed > 115200) {
+		outb( IER_SFIF_IE, iobase+IER);
+		pc87108_dma_receive( idev);
+	} else
+		outb( IER_RXHDL_IE, iobase+IER);
+    	
+	/* Restore BSR */
+	outb( bank, iobase+BSR);
+}
+
+/*
+ * Function pc87108_hard_xmit (skb, dev)
+ *
+ *    Transmit the frame!
+ *
+ */
+static int pc87108_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	__u8 bank;
+	int mtt;
+	
+	idev = (struct irda_device *) dev->priv;
+
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+	iobase = idev->io.iobase;
+
+	DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+
+	if ( dev->tbusy) {
+		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+			
+		return -EBUSY;
+	}
+	
+	/* Lock transmit buffer */
+	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	/* Decide if we should use PIO or DMA transfer */
+	if ( idev->io.baudrate > 115200) {
+		memcpy( idev->tx_buff.data, skb->data, skb->len);
+		idev->tx_buff.len = skb->len;
+		idev->tx_buff.head = idev->tx_buff.data;
+		idev->tx_buff.offset = 0;
+
+		mtt = irda_get_mtt( skb);
+	        if ( mtt > 50) {
+			/* Adjust for timer resolution */
+			mtt = mtt / 125 + 1;
+
+			/* Setup timer */
+			switch_bank( iobase, BANK4);
+			outb( mtt & 0xff, iobase+TMRL);
+			outb(( mtt >> 8) & 0x0f, iobase+TMRH);
+			
+			/* Start timer */
+			outb( IRCR1_TMR_EN, iobase+IRCR1);
+			idev->io.direction = IO_XMIT;
+			
+			/* Enable timer interrupt */
+			switch_bank( iobase, BANK0);
+			outb( IER_TMR_IE, iobase+IER);
+		} else {
+			/* Use udelay for delays less than 50 us. */
+			if (mtt)
+				udelay( mtt);
+
+			/* Enable DMA interrupt */
+			switch_bank( iobase, BANK0);
+	 		outb( IER_DMA_IE, iobase+IER);
+	     		pc87108_dma_write( idev, iobase);
+		}
+        } else {
+	        idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, 
+						    idev->tx_buff.truesize);
+		
+		idev->tx_buff.offset = 0;
+		idev->tx_buff.head = idev->tx_buff.data;
+		
+		/* Add interrupt on tx low level (will fire immediately) */
+		switch_bank( iobase, BANK0);
+		outb( IER_TXLDL_IE, iobase+IER);
+	}
+	dev_kfree_skb( skb);
+
+	/* Restore bank register */
+	outb( bank, iobase+BSR);
+
+	return 0;
+}
+
+/*
+ * Function pc87108_dma_xmit (idev, iobase)
+ *
+ *    Transmit data using DMA
+ *
+ */
+static void pc87108_dma_write( struct irda_device *idev, int iobase)
+{
+	int bsr;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bsr = inb( iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, BANK0);
+	outb( inb( iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+	setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+		   DMA_MODE_WRITE);
+	
+	/* idev->media_busy = TRUE; */
+	idev->io.direction = IO_XMIT;
+	
+	/* Choose transmit DMA channel  */ 
+	switch_bank(iobase, BANK2);
+	outb( inb( iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, 
+	      iobase+ECR1);
+	
+	/* Enable DMA */
+ 	switch_bank( iobase, BANK0);	
+	outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+	/* Restore bank register */
+	outb( bsr, iobase+BSR);
+}
+
+/*
+ * Function pc87108_pio_xmit (idev, iobase)
+ *
+ *    Transmit data using PIO. Returns the number of bytes that actually
+ *    got transfered
+ *
+ */
+static int pc87108_pio_write( int iobase, __u8 *buf, int len, int fifo_size)
+{
+	int actual = 0;
+	__u8 bank;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	switch_bank( iobase, BANK0);
+	if (!(inb_p( iobase+LSR) & LSR_TXEMP)) {
+		DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+
+		fifo_size -= 17;
+		DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+	}
+
+	/* Fill FIFO with current frame */
+	while (( fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb( buf[actual++], iobase+TXD);
+	}
+        
+	DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+	       fifo_size, actual, len);
+
+	/* Restore bank */
+	outb( bank, iobase+BSR);
+
+	return actual;
+}
+
+/*
+ * Function pc87108_dma_xmit_complete (idev)
+ *
+ *    The transfer of a frame in finished. This function will only be called 
+ *    by the interrupt handler
+ *
+ */
+static void pc87108_dma_xmit_complete( struct irda_device *idev)
+{
+	int iobase;
+	__u8 bank;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase;
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank( iobase, BANK0);
+	outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+	
+	/* Check for underrrun! */
+	if ( inb( iobase+ASCR) & ASCR_TXUR) {
+		idev->stats.tx_errors++;
+		idev->stats.tx_fifo_errors++;
+		
+		/* Clear bit, by writing 1 to it */
+		outb( ASCR_TXUR, iobase+ASCR);
+	} else {
+		idev->stats.tx_packets++;
+		idev->stats.tx_bytes +=  idev->tx_buff.len;
+	}
+	
+	/* Unlock tx_buff and request another frame */
+	idev->netdev.tbusy = 0; /* Unlock */
+	idev->media_busy = FALSE;
+	
+	/* Tell the network layer, that we can accept more frames */
+	mark_bh( NET_BH);
+
+	/* Restore bank */
+	outb( bank, iobase+BSR);
+}
+
+/*
+ * Function pc87108_dma_receive (idev)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+static int pc87108_dma_receive( struct irda_device *idev) 
+{
+	struct pc87108 *self;
+	int iobase;
+	__u8 bsr;
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	DEBUG( 4, __FUNCTION__ "\n");
+
+	self = idev->priv;
+	iobase= idev->io.iobase;
+
+	/* Save current bank */
+	bsr = inb( iobase+BSR);
+
+	/* Disable DMA */
+	switch_bank( iobase, BANK0);
+	outb( inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+	setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+		   DMA_MODE_READ);
+	
+	/* driver->media_busy = FALSE; */
+	idev->io.direction = IO_RECV;
+	idev->rx_buff.head = idev->rx_buff.data;
+	idev->rx_buff.offset = 0;
+
+	/* Reset Rx FIFO. This will also flush the ST_FIFO */
+	outb( FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
+
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, BANK2);
+	outb(( inb( iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL, 
+	      iobase+ECR1);
+	
+	/* enable DMA */
+	switch_bank(iobase, BANK0);
+	outb( inb( iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+	/* Restore bank register */
+	outb( bsr, iobase+BSR);
+	
+	DEBUG( 4, __FUNCTION__ "(), done!\n");	
+	
+	return 0;
+}
+
+/*
+ * Function pc87108_dma_receive_complete (idev)
+ *
+ *    Finished with receiving frames
+ *
+ *    
+ */
+static int pc87108_dma_receive_complete( struct irda_device *idev, int iobase)
+{
+	struct sk_buff *skb;
+	struct pc87108 *self;
+	struct st_fifo *st_fifo;
+	int len;
+	__u8 bank;
+	__u8 status;
+
+	self = idev->priv;
+	st_fifo = &self->st_fifo;
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+	
+	iobase = idev->io.iobase;
+
+	/* Read status FIFO */
+	switch_bank(iobase, BANK5);
+	while (( status = inb( iobase+FRM_ST)) & FRM_ST_VLD) {
+		st_fifo->entries[ st_fifo->tail].status = status;
+
+		st_fifo->entries[ st_fifo->tail].len  = inb(iobase+RFLFL);
+		st_fifo->entries[ st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+		
+		st_fifo->tail++;
+		st_fifo->len++;
+	}
+	
+	/* Try to process all entries in status FIFO */
+	switch_bank( iobase, BANK0);
+	while ( st_fifo->len) {
+      
+		/* Get first entry */
+		status = st_fifo->entries[ st_fifo->head].status;
+		len    = st_fifo->entries[ st_fifo->head].len;
+		st_fifo->head++;
+		st_fifo->len--;
+
+		/* Check for errors */
+		if ( status & FRM_ST_ERR_MSK) {
+			if ( status & FRM_ST_LOST_FR) {
+				/* Add number of lost frames to stats */
+				idev->stats.rx_errors += len;	
+			} else {
+				/* Skip frame */
+				idev->stats.rx_errors++;
+				
+				idev->rx_buff.offset  += len;
+				idev->rx_buff.head += len;
+			
+				if ( status & FRM_ST_MAX_LEN)
+					idev->stats.rx_length_errors++;
+				
+				if ( status & FRM_ST_PHY_ERR) 
+					idev->stats.rx_frame_errors++;
+				
+				if ( status & FRM_ST_BAD_CRC) 
+					idev->stats.rx_crc_errors++;
+			}
+			/* The errors below can be reported in both cases */
+			if ( status & FRM_ST_OVR1)
+				idev->stats.rx_fifo_errors++;
+			
+			if ( status & FRM_ST_OVR2)
+				idev->stats.rx_fifo_errors++;
+			
+		} else {
+			/* Check if we have transfered all data to memory */
+			if ( inb( iobase+LSR) & LSR_RXDA) {
+				/* Put this entry back in fifo */
+				st_fifo->head--;
+				st_fifo->len++;
+				st_fifo->entries[ st_fifo->head].status = status;
+				st_fifo->entries[ st_fifo->head].len = len;
+
+				/* Restore bank register */
+				outb( bank, iobase+BSR);
+			
+				return FALSE; 	/* I'll be back! */
+			}
+
+			/* Should be OK then */			
+			skb = dev_alloc_skb( len+1);
+			if (skb == NULL)  {
+				printk( KERN_INFO __FUNCTION__ 
+					"(), memory squeeze, dropping frame.\n");
+				/* Restore bank register */
+				outb( bank, iobase+BSR);
+
+				return FALSE;
+			}
+			
+			/* Make sure IP header gets aligned */
+			skb_reserve( skb, 1); 
+
+			/* Copy frame without CRC */
+			if ( idev->io.baudrate < 4000000) {
+				skb_put( skb, len-2);
+				memcpy( skb->data, idev->rx_buff.head, len-2);
+			} else {
+				skb_put( skb, len-4);
+				memcpy( skb->data, idev->rx_buff.head, len-4);
+			}
+
+			/* Move to next frame */
+			idev->rx_buff.offset += len;
+			idev->rx_buff.head += len;
+			idev->stats.rx_packets++;
+
+			skb->dev = &idev->netdev;
+			skb->mac.raw  = skb->data;
+			skb->protocol = htons(ETH_P_IRDA);
+			netif_rx( skb);
+		}
+	}
+	/* Restore bank register */
+	outb( bank, iobase+BSR);
+
+	return TRUE;
+}
+
+/*
+ * Function pc87108_pio_receive (idev)
+ *
+ *    Receive all data in receiver FIFO
+ *
+ */
+static void pc87108_pio_receive( struct irda_device *idev) 
+{
+	__u8 byte = 0x00;
+	int iobase;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	iobase = idev->io.iobase;
+	
+	if ( idev->rx_buff.len == 0) {
+		idev->rx_buff.head = idev->rx_buff.data;
+	}
+
+	/*  Receive all characters in Rx FIFO */
+	do {
+		byte = inb( iobase+RXD);
+		async_unwrap_char( idev, byte);
+
+	} while ( inb( iobase+LSR) & LSR_RXDA); /* Data available */	
+}
+
+/*
+ * Function pc87108_sir_interrupt (idev, eir)
+ *
+ *    Handle SIR interrupt
+ *
+ */
+static __u8 pc87108_sir_interrupt( struct irda_device *idev, int eir)
+{
+	int len;
+	int actual;
+	__u8 new_ier = 0;
+
+	/* Transmit FIFO low on data */
+	if ( eir & EIR_TXLDL_EV) {
+		/* Write data left in transmit buffer */
+		len = idev->tx_buff.len - idev->tx_buff.offset;
+
+		ASSERT( len > 0, return 0;);
+		actual = pc87108_pio_write( idev->io.iobase, 
+					    idev->tx_buff.head, 
+					    len, idev->io.fifo_size);
+		idev->tx_buff.offset += actual;
+		idev->tx_buff.head += actual;
+		
+		idev->io.direction = IO_XMIT;
+		ASSERT( actual <= len, return 0;);
+
+		/* Check if finished */
+		if ( actual == len) { 
+			DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+			idev->netdev.tbusy = 0; /* Unlock */
+			idev->stats.tx_packets++;
+
+		        mark_bh(NET_BH);	
+
+			new_ier |= IER_TXEMP_IE;
+		} else
+			new_ier |= IER_TXLDL_IE;
+	}
+	/* Check if transmission has completed */
+	if ( eir & EIR_TXEMP_EV) {
+		
+		/* Turn around and get ready to receive some data */
+		idev->io.direction = IO_RECV;
+		new_ier |= IER_RXHDL_IE;
+	}
+
+	/* Rx FIFO threshold or timeout */
+	if ( eir & EIR_RXHDL_EV) {
+		pc87108_pio_receive( idev);
+
+		/* Keep receiving */
+		new_ier |= IER_RXHDL_IE;
+	}
+	return new_ier;
+}
+
+/*
+ * Function pc87108_fir_interrupt (idev, eir)
+ *
+ *    Handle MIR/FIR interrupt
+ *
+ */
+static __u8 pc87108_fir_interrupt( struct irda_device *idev, int iobase,
+				   int eir)
+{
+	__u8 new_ier = 0;
+	__u8 bank;
+
+	bank = inb( iobase+BSR);
+	
+	/* Status event, or end of frame detected in FIFO */
+	if ( eir & (EIR_SFIF_EV|EIR_LS_EV)) {
+		if ( pc87108_dma_receive_complete( idev, iobase)) {
+
+			/* Wait for next status FIFO interrupt */
+			new_ier |= IER_SFIF_IE;
+		} else {
+			/* DMA not finished yet */
+
+			/* Set timer value, resolution 125 us */
+			switch_bank( iobase, BANK4);
+			outb( 0x0f, iobase+TMRL); /* 125 us */
+			outb( 0x00, iobase+TMRH);
+
+			/* Start timer */
+			outb( IRCR1_TMR_EN, iobase+IRCR1);
+
+			new_ier |= IER_TMR_IE;
+		}
+	}
+	/* Timer finished */
+	if ( eir & EIR_TMR_EV) {
+		/* Disable timer */
+		switch_bank( iobase, BANK4);
+		outb( 0, iobase+IRCR1);
+
+		/* Clear timer event */
+		switch_bank(iobase, BANK0);
+		outb( ASCR_CTE, iobase+ASCR);
+
+		/* Check if this is a TX timer interrupt */
+		if ( idev->io.direction == IO_XMIT) {
+			pc87108_dma_write( idev, iobase);
+
+			/*  Interrupt on DMA */
+			new_ier |= IER_DMA_IE;
+		} else {
+			/* Check if DMA has now finished */
+			pc87108_dma_receive_complete( idev, iobase);
+
+			new_ier |= IER_SFIF_IE;
+		}
+	}	
+	/* Finished with transmission */
+	if ( eir & EIR_DMA_EV) {
+		pc87108_dma_xmit_complete( idev);
+		
+		/* Check if there are more frames to be transmitted */
+		if ( irda_device_txqueue_empty( idev)) {
+			/* Prepare for receive */
+			pc87108_dma_receive( idev);
+			
+			new_ier = IER_LS_IE|IER_SFIF_IE;
+		}
+	}
+	outb( bank, iobase+BSR);
+
+	return new_ier;
+}
+
+/*
+ * Function pc87108_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	__u8 bsr, eir, ier;
+	int iobase;
+
+	struct irda_device *idev = (struct irda_device *) dev_id;
+
+	if (idev == NULL) {
+		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
+			driver_name, irq);
+		return;
+	}
+
+	idev->netdev.interrupt = 1;
+
+	iobase = idev->io.iobase;
+
+	/* Save current bank */
+	bsr = inb( iobase+BSR);
+
+	switch_bank( iobase, BANK0);	
+	ier = inb( iobase+IER); 
+	eir = inb( iobase+EIR) & ier; /* Mask out the interesting ones */ 
+
+	outb( 0, iobase+IER); /* Disable interrupts */
+	
+	if ( eir) {
+		/* Dispatch interrupt handler for the current speed */
+		if ( idev->io.baudrate > 115200)
+			ier = pc87108_fir_interrupt( idev, iobase, eir);
+		else
+			ier = pc87108_sir_interrupt( idev, eir);
+	}
+
+	outb( ier, iobase+IER);   /* Restore interrupts */
+	outb( bsr, iobase+BSR);   /* Restore bank register */
+
+	idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function pc87108_wait_until_sent (idev)
+ *
+ *    This function should put the current thread to sleep until all data 
+ *    have been sent, so it is safe to f.eks. change the speed.
+ */
+static void pc87108_wait_until_sent( struct irda_device *idev)
+{
+	/* Just delay 60 ms */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(6);
+}
+
+/*
+ * Function pc87108_is_receiving (idev)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int pc87108_is_receiving( struct irda_device *idev)
+{
+	int status = FALSE;
+	int iobase;
+	__u8 bank;
+
+	ASSERT( idev != NULL, return FALSE;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+	if ( idev->io.baudrate > 115200) {
+		iobase = idev->io.iobase;
+
+		/* Check if rx FIFO is not empty */
+		bank = inb( iobase+BSR);
+		switch_bank( iobase, BANK2);
+		if (( inb( iobase+RXFLV) & 0x3f) != 0) {
+			/* We are receiving something */
+			status =  TRUE;
+		}
+		outb( bank, iobase+BSR);
+	} else 
+		status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+	
+	return status;
+}
+
+/*
+ * Function pc87108_net_init (dev)
+ *
+ *    Initialize network device
+ *
+ */
+static int pc87108_net_init( struct device *dev)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Setup to be a normal IrDA network device driver */
+	irda_device_setup( dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+
+/*
+ * Function pc87108_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int pc87108_net_open( struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	__u8 bank;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+	
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	
+	iobase = idev->io.iobase;
+
+	if (request_irq( idev->io.irq, pc87108_interrupt, 0, idev->name, 
+			 (void *) idev)) {
+		return -EAGAIN;
+	}
+	/*
+	 * Always allocate the DMA channel after the IRQ,
+	 * and clean up on failure.
+	 */
+	if (request_dma(idev->io.dma, idev->name)) {
+		free_irq( idev->io.irq, idev);
+		return -EAGAIN;
+	}
+		
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+	
+	/* turn on interrupts */
+	switch_bank( iobase, BANK0);
+	outb( IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+
+	/* Restore bank register */
+	outb( bank, iobase+BSR);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function pc87108_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int pc87108_net_close(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	__u8 bank;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	ASSERT( dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+	
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	
+	iobase = idev->io.iobase;
+
+	disable_dma( idev->io.dma);
+
+	/* Save current bank */
+	bank = inb( iobase+BSR);
+
+	/* Disable interrupts */
+	switch_bank( iobase, BANK0);
+	outb( 0, iobase+IER); 
+       
+	free_irq( idev->io.irq, idev);
+	free_dma( idev->io.dma);
+
+	/* Restore bank register */
+	outb( bank, iobase+BSR);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *    
+ *
+ */
+int init_module(void)
+{
+	pc87108_init();
+
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    
+ *
+ */
+void cleanup_module(void)
+{
+	pc87108_cleanup();
+}
+
+#endif
+
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.1.131/linux/drivers/net/irda/tekram.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/tekram.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,312 @@
+/*********************************************************************
+ *                
+ * Filename:      tekram.c
+ * Version:       0.3
+ * 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 Dec 14 11:48:37 1998
+ * 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/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 tekram_reset( struct irda_device *dev, int unused);
+static void tekram_open( struct irda_device *dev, int type);
+static void tekram_close( struct irda_device *dev);
+static void tekram_change_speed( struct irda_device *dev, int baud);
+static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos);
+
+static struct dongle dongle = {
+	TEKRAM_DONGLE,
+	tekram_open,
+	tekram_close,
+	tekram_reset,
+	tekram_change_speed,
+	tekram_init_qos,
+};
+
+__initfunc(void tekram_init(void))
+{
+	irtty_register_dongle( &dongle);
+}
+
+void tekram_cleanup(void)
+{
+	irtty_unregister_dongle( &dongle);
+}
+
+static void tekram_open( struct irda_device *dev, int type)
+{
+	strcat( dev->name, " <-> tekram");
+	
+	MOD_INC_USE_COUNT;
+}
+
+static void tekram_close( struct irda_device *dev)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+/*
+ * Function tekram_change_speed (tty, baud)
+ *
+ *    Set the speed for the Tekram IRMate 210 type dongle. Warning, this 
+ *    function must be called with a process context!
+ *
+ *    Algorithm
+ *    1. clear DTR 
+ *    2. set RTS, and wait at least 7 us
+ *    3. send Control Byte to the IR-210 through TXD to set new baud rate
+ *       wait until the stop bit of Control Byte is sent (for 9600 baud rate, 
+ *       it takes about 100 msec)
+ *    5. clear RTS (return to NORMAL Operation)
+ *    6. wait at least 50 us, new setting (baud rate, etc) takes effect here 
+ *       after
+ */
+static void tekram_change_speed( struct irda_device *dev, int baud)
+{
+	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");
+
+	ASSERT( dev != NULL, return;);
+	ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	self = (struct irtty_cb *) dev->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 (baud) {
+	case 9600:
+	default:
+		cflag |= B9600;
+		byte = 4;
+		break;
+	case 19200:
+		cflag |= B19200;
+		byte = 3;
+		break;
+	case 34800:
+		cflag |= B38400;
+		byte = 2;
+		break;
+	case 57600:
+		cflag |= B57600;
+		byte = 1;
+		break;
+	case 115200:
+		cflag |= B115200;
+		byte = 0;
+		break;
+	}
+
+	/* Set DTR, Clear RTS */
+	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
+	arg = TIOCM_DTR;
+	
+	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);
+	
+	/* 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);
+	
+	/* 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;
+	
+	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);
+
+	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);	
+}
+
+/*
+ * Function tekram_reset (driver)
+ *
+ *      This function resets the tekram dongle. Warning, this function 
+ *      must be called with a process context!! 
+ *
+ *      Algorithm:
+ *    	  0. set RTS and DTR, and wait 50 ms 
+ *           ( power off the IR-210 )
+ *        1. clear RTS 
+ *        2. set DTR, and wait at least 1 ms 
+ *        3. clear DTR to SPACE state, wait at least 50 us for further 
+ *         operation
+ */
+void tekram_reset( struct irda_device *dev, int unused)
+{
+	struct irtty_cb *self;
+	struct tty_struct *tty;
+	int arg = 0;
+	mm_segment_t fs;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( dev != NULL, return;);
+	ASSERT( dev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	self = (struct irtty_cb *) dev->priv;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRTTY_MAGIC, return;);
+
+	tty = self->tty;
+	if ( !tty)
+		return;
+
+	DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
+	arg = TIOCM_RTS | TIOCM_DTR;
+	
+	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);
+
+	/* 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;
+	
+	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);
+
+	/* 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 */
+	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);
+	
+	/* Finished! */
+}
+
+/*
+ * Function tekram_init_qos (qos)
+ *
+ *    Initialize QoS capabilities
+ *
+ */
+static void tekram_init_qos( struct irda_device *idev, struct qos_info *qos)
+{
+	qos->baud_rate.bits &= IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
+	qos->min_turn_time.bits &= 0xfe; /* All except 0 ms */
+}
+
+#ifdef MODULE
+		
+/*
+ * Function init_module (void)
+ *
+ *    Initialize Tekram module
+ *
+ */
+int init_module(void)
+{
+	tekram_init();
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup Tekram module
+ *
+ */
+void cleanup_module(void)
+{
+        tekram_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.1.131/linux/drivers/net/irda/w83977af_ir.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/w83977af_ir.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,1273 @@
+/*********************************************************************
+ *                
+ * Filename:      w83977af_ir.c
+ * Version:       0.8
+ * Description:   FIR/MIR driver for the Winbond W83977AF Super I/O chip
+ * Status:        Experimental.
+ * Author:        Paul VanderSpek
+ * Created at:    Wed Nov  4 11:46:16 1998
+ * Modified at:   Mon Dec 14 21:51:53 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Corel Computer Corp.
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Paul VanderSpek nor Corel Computer Corp. admit liability
+ *     nor provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ *     If you find bugs in this file, its very likely that the same bug
+ *     will also be in w83977af_ir.c since the implementations is quite
+ *     similar.
+ *
+ *     Notice that all functions that needs to access the chip in _any_
+ *     way, must save BSR register on entry, and restore it on exit. 
+ *     It is _very_ important to follow this policy!
+ *
+ *         __u8 bank;
+ *     
+ *         bank = inb( iobase+BSR);
+ *  
+ *         do_your_stuff_here();
+ *
+ *         outb( bank, iobase+BSR);
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/w83977af.h>
+#include <net/irda/w83977af_ir.h>
+
+#define NETWINDER
+
+static char *driver_name = "w83977af_ir";
+
+#define CHIP_IO_EXTENT 8
+
+static unsigned int io[] = { 0x400, ~0, ~0, ~0 };
+static unsigned int irq[] = { 22, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0 };
+
+static struct irda_device *dev_self[] = { NULL, NULL, NULL, NULL};
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+static struct st_fifo_entry prev;
+
+/* Some prototypes */
+static int  w83977af_open( int i, unsigned int iobase, unsigned int irq, 
+			   unsigned int dma);
+static int  w83977af_close( struct irda_device *idev);
+static int  w83977af_probe( int iobase, int irq, int dma);
+static int  w83977af_dma_receive(struct irda_device *idev); 
+static int  w83977af_dma_receive_complete(struct irda_device *idev);
+static int  w83977af_hard_xmit( struct sk_buff *skb, struct device *dev);
+static int  w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size);
+static void w83977af_dma_write( struct irda_device *idev, int iobase);
+static void w83977af_change_speed( struct irda_device *idev, int baud);
+static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void w83977af_wait_until_sent( struct irda_device *idev);
+static int w83977af_is_receiving( struct irda_device *idev);
+
+static int w83977af_net_init( struct device *dev);
+static int w83977af_net_open( struct device *dev);
+static int w83977af_net_close( struct device *dev);
+
+/*
+ * Function w83977af_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+__initfunc(int w83977af_init(void))
+{
+	int i;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	prev.status = 0;
+
+	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+		int ioaddr = io[i];
+		if (check_region(ioaddr, CHIP_IO_EXTENT))
+			continue;
+		if (w83977af_open( i, io[i], irq[i], dma[i]) == 0)
+			return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Function w83977af_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+void w83977af_cleanup(void)
+{
+	int i;
+
+        DEBUG( 4, __FUNCTION__ "()\n");
+
+	for ( i=0; i < 4; i++) {
+		if ( dev_self[i])
+			w83977af_close( dev_self[i]);
+	}
+}
+#endif /* MODULE */
+
+/*
+ * Function w83977af_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+int w83977af_open( int i, unsigned int iobase, unsigned int irq, 
+		   unsigned int dma)
+{
+	struct irda_device *idev;
+	int ret;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	if ( w83977af_probe( iobase, irq, dma) == -1)
+		return -1;
+
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	idev = kmalloc( sizeof(struct irda_device), GFP_KERNEL);
+	if ( idev == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset( idev, 0, sizeof(struct irda_device));
+   
+	/* Need to store self somewhere */
+	dev_self[i] = idev;
+
+	/* Initialize IO */
+	idev->io.iobase    = iobase;
+        idev->io.irq       = irq;
+        idev->io.io_ext    = CHIP_IO_EXTENT;
+        idev->io.dma       = dma;
+        idev->io.fifo_size = 32;
+
+	/* Lock the port that we need */
+	ret = check_region( idev->io.iobase, idev->io.io_ext);
+	if ( ret < 0) { 
+		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		       idev->io.iobase);
+		/* w83977af_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies( &idev->qos);
+	
+	/* The only value we must override it the baudrate */
+
+	/* FIXME: The HP HDLS-1100 does not support 1152000! */
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+
+	/* The HP HDLS-1100 needs 1 ms according to the specs */
+	idev->qos.min_turn_time.bits = 0x03; /* 1ms and more */
+	irda_qos_bits_to_value( &idev->qos);
+
+	/* Specify which buffer allocation policy we need */
+	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	idev->rx_buff.truesize = 14384; 
+	idev->tx_buff.truesize = 4000;
+	
+	/* Initialize callbacks */
+	idev->hard_xmit       = w83977af_hard_xmit;
+	idev->change_speed    = w83977af_change_speed;
+	idev->wait_until_sent = w83977af_wait_until_sent;
+        idev->is_receiving    = w83977af_is_receiving;
+
+	/* Override the network functions we need to use */
+	idev->netdev.init = w83977af_net_init;
+	idev->netdev.hard_start_xmit = w83977af_hard_xmit;
+	idev->netdev.open = w83977af_net_open;
+	idev->netdev.stop = w83977af_net_close;
+
+	/* Open the IrDA device */
+	irda_device_open( idev, driver_name, NULL);
+	
+	return 0;
+}
+
+/*
+ * Function w83977af_close (idev)
+ *
+ *    Close driver instance
+ *
+ */
+static int w83977af_close( struct irda_device *idev)
+{
+	int iobase;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+        iobase = idev->io.iobase;
+
+	/* enter PnP configuration mode */
+	w977_efm_enter();
+
+	w977_select_device(W977_DEVICE_IR);
+
+	/* Deactivate device */
+	w977_write_reg(0x30, 0x00);
+
+	w977_efm_exit();
+
+	/* Release the PORT that this driver is using */
+	DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n", 
+	      idev->io.iobase);
+	release_region( idev->io.iobase, idev->io.io_ext);
+
+	irda_device_close( idev);
+
+	return 0;
+}
+
+/*
+ * Function w83977af_probe (iobase, irq, dma)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+int w83977af_probe( int iobase, int irq, int dma)
+{
+	int version;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	/* Enter PnP configuration mode */
+	w977_efm_enter();
+
+	w977_select_device(W977_DEVICE_IR);
+
+	/* Configure PnP port, IRQ, and DMA channel */
+	w977_write_reg(0x60, (iobase >> 8) & 0xff);
+	w977_write_reg(0x61, (iobase) & 0xff);
+	w977_write_reg(0x70, 0x06);
+#ifdef NETWINDER
+	w977_write_reg(0x74, dma+1); /* Netwinder uses 1 higher than Linux */
+#else
+	w977_write_reg(0x74, dma);   
+#endif
+	w977_write_reg(0x75, dma);   /* Disable Tx DMA */
+	
+	/* Set append hardware CRC, enable IR bank selection */	
+	w977_write_reg(0xf0, APEDCRC|ENBNKSEL);
+
+	/* Activate device */
+	w977_write_reg(0x30, 0x01);
+
+	w977_efm_exit();
+
+ 	/* Disable Advanced mode */
+ 	switch_bank( iobase, SET2);
+ 	outb(iobase+2, 0x00);  
+
+	/* Turn on UART (global) interrupts */
+	switch_bank( iobase, SET0);
+	outb( HCR_EN_IRQ, iobase+HCR);
+	
+	/* Switch to advanced mode */
+	switch_bank( iobase, SET2);
+	outb( inb( iobase+ADCR1) | ADCR1_ADV_SL, iobase+ADCR1);
+
+	/* Set default IR-mode */
+	switch_bank( iobase, SET0);
+	outb( HCR_SIR, iobase+HCR);
+
+	/* Read the Advanced IR ID */
+	switch_bank(iobase, SET3);
+	version =  inb( iobase+AUID);
+	
+	/* Should be 0x1? */
+	if (0x10 != (version & 0xf0)) {
+		DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
+		return -1;
+	}
+	
+	/* Set FIFO size to 32 */
+	switch_bank( iobase, SET2);
+	outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+	
+	/* Set FIFO threshold to TX17, RX16 */
+	switch_bank(iobase, SET0);	
+	outb(UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO,iobase+UFR);
+/* 	outb( 0xa7, iobase+UFR); */
+
+	/* Receiver frame length */
+	switch_bank( iobase, SET4);
+	outb( 2048 & 0xff, iobase+6);
+	outb(( 2048 >> 8) & 0x1f, iobase+7);
+
+	/* 
+	 * Init HP HSDL-1100 transceiver. 
+	 * 
+	 * Set IRX_MSL since we have 2 * receive paths IRRX, and
+	 * IRRXH. Clear IRSL0D since we want IRSL0 * to be a input pin used
+	 * for IRRXH 
+	 *
+	 *   IRRX  pin 37 connected to receiver 
+	 *   IRTX  pin 38 connected to transmitter
+	 *   FIRRX pin 39 connected to receiver      (IRSL0) 
+	 *   CIRRX pin 40 connected to pin 37
+	 */
+	switch_bank( iobase, SET7);
+	outb( 0x40, iobase+7);
+		
+	DEBUG(0, "W83977AF (IR) driver loaded. Version: 0x%02x\n", version);
+	
+	return 0;
+}
+
+/*
+ * Function w83977af_change_speed (idev, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+void w83977af_change_speed( struct irda_device *idev, int speed)
+{
+	int ir_mode = HCR_SIR;
+	int iobase; 
+	__u8 set;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase;
+
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
+	/* Save current bank */
+	set = inb( iobase+SSR);
+
+	/* Disable interrupts */
+	switch_bank( iobase, SET0);
+	outb( 0, iobase+ICR);
+
+	/* Select Set 2 */
+	switch_bank( iobase, SET2);
+
+	outb( 0x00, iobase+ABHL);
+	switch ( speed) {
+	case 9600:   outb( 0x0c, iobase+ABLL); break;
+	case 19200:  outb( 0x06, iobase+ABLL); break;
+	case 37600:  outb( 0x03, iobase+ABLL); break;
+	case 57600:  outb( 0x02, iobase+ABLL); break;
+	case 115200: outb( 0x01, iobase+ABLL); break;
+	case 576000:
+		ir_mode = HCR_MIR_576;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		break;
+	case 1152000:
+		ir_mode = HCR_MIR_1152;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		break;
+	case 4000000:
+		ir_mode = HCR_FIR;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		break;
+	default:
+		ir_mode = HCR_FIR;
+		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		break;
+	}
+
+	/* Set speed mode */
+	switch_bank(iobase, SET0);
+	outb( ir_mode, iobase+HCR);
+
+	/* set FIFO size to 32 */
+	switch_bank( iobase, SET2);
+	outb( ADCR2_RXFS32|ADCR2_TXFS32, iobase+ADCR2);	
+	
+	/* set FIFO threshold to TX17, RX16 */
+	switch_bank(iobase, SET0);
+	outb( UFR_RXTL|UFR_TXTL|UFR_TXF_RST|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+	
+	idev->netdev.tbusy = 0;
+	
+	/* Enable some interrupts so we can receive frames */
+	switch_bank(iobase, SET0);
+	if ( speed > 115200) {
+		outb( ICR_EFSFI, iobase+ICR);
+		w83977af_dma_receive( idev);
+	} else
+		outb( ICR_ERBRI, iobase+ICR);
+    	
+	/* Restore SSR */
+	outb( set, iobase+SSR);
+}
+
+/*
+ * Function w83977af_hard_xmit (skb, dev)
+ *
+ *    Sets up a DMA transfer to send the current frame.
+ *
+ */
+int w83977af_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	__u8 set;
+	int mtt;
+	
+	idev = (struct irda_device *) dev->priv;
+
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+	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)
+		return -EBUSY;
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+	
+	/* Decide if we should use PIO or DMA transfer */
+	if ( idev->io.baudrate > 115200) {
+		memcpy( idev->tx_buff.data, skb->data, skb->len);
+		idev->tx_buff.len = skb->len;
+		idev->tx_buff.head = idev->tx_buff.data;
+		idev->tx_buff.offset = 0;
+		
+		mtt = irda_get_mtt( skb);
+	        if ( mtt > 50) {
+			/* Adjust for timer resolution */
+			mtt /= 1000+1;
+
+			/* Setup timer */
+			switch_bank( iobase, SET4);
+			outb( mtt & 0xff, iobase+TMRL);
+			outb(( mtt >> 8) & 0x0f, iobase+TMRH);
+			
+			/* Start timer */
+			outb( IR_MSL_EN_TMR, iobase+IR_MSL);
+			idev->io.direction = IO_XMIT;
+			
+			/* Enable timer interrupt */
+			switch_bank( iobase, SET0);
+			outb( ICR_ETMRI, iobase+ICR);
+		} else {
+			if ( mtt)
+				udelay( mtt);
+
+			/* Enable DMA interrupt */
+			switch_bank( iobase, SET0);
+	 		outb( ICR_EDMAI, iobase+ICR);
+	     		w83977af_dma_write( idev, iobase);
+		}
+	} else {
+		idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, 
+						    idev->tx_buff.truesize);
+		
+		idev->tx_buff.offset = 0;
+		idev->tx_buff.head = idev->tx_buff.data;
+		
+		/* Add interrupt on tx low level (will fire immediately) */
+		switch_bank( iobase, SET0);
+		outb( ICR_ETXTHI, iobase+ICR);
+	}
+	dev_kfree_skb( skb);
+
+	/* Restore set register */
+	outb( set, iobase+SSR);
+
+	return 0;
+}
+
+
+/*
+ * Function w83977af_dma_write (idev, iobase)
+ *
+ *    
+ *
+ */
+static void w83977af_dma_write( struct irda_device *idev, int iobase)
+{
+	__u8 set;
+
+        DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, SET0);
+	outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+	
+	setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+		   DMA_MODE_WRITE);
+	
+	/* idev->media_busy = TRUE; */
+	idev->io.direction = IO_XMIT;
+	
+	/* Choose transmit DMA channel  */ 
+	switch_bank(iobase, SET2);
+	outb( inb( iobase+ADCR1) | ADCR1_D_CHSW|ADCR1_DMA_F|ADCR1_ADV_SL, 
+	      iobase+ADCR1);
+	
+	/* Enable DMA */
+ 	switch_bank( iobase, SET0);
+	outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+	
+	/* Restore set register */
+	outb( set, iobase+SSR);
+}
+
+/*
+ * Function w83977af_pio_write (iobase, buf, len, fifo_size)
+ *
+ *    
+ *
+ */
+static int w83977af_pio_write( int iobase, __u8 *buf, int len, int fifo_size)
+{
+	int actual = 0;
+	__u8 set;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Save current bank */
+	set = inb( iobase+SSR);
+
+	switch_bank( iobase, SET0);
+	if (!( inb_p( iobase+USR) & USR_TSRE)) {
+		DEBUG( 4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+
+		fifo_size -= 17;
+		DEBUG( 4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+	}
+
+	/* Fill FIFO with current frame */
+	while (( fifo_size-- > 0) && (actual < len)) {
+		/* Transmit next byte */
+		outb( buf[actual++], iobase+TBR);
+	}
+        
+	DEBUG( 4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n", 
+	       fifo_size, actual, len);
+
+	/* Restore bank */
+	outb( set, iobase+SSR);
+
+	return actual;
+}
+
+/*
+ * Function w83977af_dma_xmit_complete (idev)
+ *
+ *    The transfer of a frame in finished. So do the necessary things
+ *
+ *    
+ */
+void w83977af_dma_xmit_complete( struct irda_device *idev)
+{
+	int iobase;
+	__u8 set;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	iobase = idev->io.iobase;
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+
+	/* Disable DMA */
+	switch_bank(iobase, SET0);
+	outb( inb(iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+	
+	/* Check for underrrun! */
+	if ( inb( iobase+AUDR) & AUDR_UNDR) {
+		DEBUG( 0, __FUNCTION__ "(), Transmit underrun!\n");
+		
+		idev->stats.tx_errors++;
+		idev->stats.tx_fifo_errors++;
+
+		/* Clear bit, by writing 1 to it */
+		outb( AUDR_UNDR, iobase+AUDR);
+	} else
+		idev->stats.tx_packets++;
+
+	/* Unlock tx_buff and request another frame */
+	idev->netdev.tbusy = 0; /* Unlock */
+	idev->media_busy = FALSE;
+	
+	/* Tell the network layer, that we want more frames */
+	mark_bh( NET_BH);
+
+	/* Restore set */
+	outb( set, iobase+SSR);
+}
+
+/*
+ * Function w83977af_dma_receive (idev)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+int w83977af_dma_receive( struct irda_device *idev) 
+{
+	int iobase;
+	__u8 set;
+#ifdef NETWINDER
+	unsigned long flags;
+	__u8 hcr;
+#endif
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+	DEBUG( 0, __FUNCTION__ "\n");
+
+	iobase= idev->io.iobase;
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+
+	/* Disable DMA */
+	switch_bank( iobase, SET0);
+	outb( inb( iobase+HCR) & ~HCR_EN_DMA, iobase+HCR);
+
+#ifdef NETWINDER
+	save_flags(flags);
+	cli();
+
+	disable_dma( idev->io.dma);
+	clear_dma_ff( idev->io.dma);
+	set_dma_mode( idev->io.dma, DMA_MODE_READ);
+	set_dma_addr( idev->io.dma, virt_to_bus(idev->rx_buff.data));
+	set_dma_count( idev->io.dma, idev->rx_buff.truesize);
+#else
+	setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+		   DMA_MODE_READ);
+#endif
+	/* driver->media_busy = FALSE; */
+	idev->io.direction = IO_RECV;
+	idev->rx_buff.head = idev->rx_buff.data;
+	idev->rx_buff.offset = 0;
+
+	/* 
+	 * Reset Rx FIFO. This will also flush the ST_FIFO, it's very 
+	 * important that we don't reset the Tx FIFO since it might not
+	 * be finished transmitting yet
+	 */
+	outb( UFR_RXTL|UFR_TXTL|UFR_RXF_RST|UFR_EN_FIFO, iobase+UFR);
+	prev.status = 0;
+
+	/* Choose DMA Rx, DMA Fairness, and Advanced mode */
+	switch_bank(iobase, SET2);
+	outb(( inb( iobase+ADCR1) & ~ADCR1_D_CHSW)|ADCR1_DMA_F|ADCR1_ADV_SL,
+	     iobase+ADCR1);
+	
+	/* Enable DMA */
+	switch_bank(iobase, SET0);
+#ifdef NETWINDER
+	hcr = inb( iobase+HCR);
+	enable_dma( idev->io.dma);
+	outb( hcr | HCR_EN_DMA, iobase+HCR);
+	restore_flags(flags);
+#else	
+	outb( inb( iobase+HCR) | HCR_EN_DMA, iobase+HCR);
+#endif
+	
+	/* Restore set */
+	outb( set, iobase+SSR);
+
+	DEBUG( 4, __FUNCTION__ "(), done!\n");	
+
+	return 0;
+}
+
+/*
+ * Function w83977af_receive_complete (idev)
+ *
+ *    Finished with receiving a frame
+ *
+ */
+int w83977af_dma_receive_complete(struct irda_device *idev)
+{
+	struct sk_buff *skb;
+	int len;
+	int iobase;
+	__u8 set;
+	__u8 status;
+
+	DEBUG( 0, __FUNCTION__ "\n");
+
+	iobase = idev->io.iobase;
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+	
+	iobase = idev->io.iobase;
+
+	switch_bank(iobase, SET5);
+	if ( prev.status & FS_FO_FSFDR) {
+		status = prev.status;
+		len = prev.len;
+
+		prev.status = 0;
+	} else {
+		status = inb( iobase+FS_FO);
+		len = inb( iobase+RFLFL);
+		len |= inb( iobase+RFLFH) << 8;
+	}
+
+	while ( status & FS_FO_FSFDR) {
+		/* Check for errors */
+		if ( status & FS_FO_ERR_MSK) {
+			if ( status & FS_FO_LST_FR) {
+				/* Add number of lost frames to stats */
+				idev->stats.rx_errors += len;	
+			} else {
+				/* Skip frame */
+				idev->stats.rx_errors++;
+				
+				idev->rx_buff.offset += len;
+				idev->rx_buff.head   += len;
+				
+				if ( status & FS_FO_MX_LEX)
+					idev->stats.rx_length_errors++;
+				
+				if ( status & FS_FO_PHY_ERR) 
+					idev->stats.rx_frame_errors++;
+				
+				if ( status & FS_FO_CRC_ERR) 
+					idev->stats.rx_crc_errors++;
+			}
+			/* The errors below can be reported in both cases */
+			if ( status & FS_FO_RX_OV)
+				idev->stats.rx_fifo_errors++;
+			
+			if ( status & FS_FO_FSF_OV)
+				idev->stats.rx_fifo_errors++;
+			
+		} else {
+			/* Check if we have transfered all data to memory */
+			switch_bank(iobase, SET0);
+			if ( inb( iobase+USR) & USR_RDR) {
+				/* Put this entry back in fifo */
+				prev.status = status;
+				prev.len = len;
+
+				/* Restore set register */
+				outb( set, iobase+SSR);
+			
+				return FALSE; 	/* I'll be back! */
+			}
+						
+			skb = dev_alloc_skb( len+1);
+			if (skb == NULL)  {
+				printk( KERN_INFO __FUNCTION__ 
+					"(), memory squeeze, dropping frame.\n");
+				/* Restore set register */
+				outb( set, iobase+SSR);
+
+				return FALSE;
+			}
+			
+			/*  Align to 20 bytes */
+			skb_reserve( skb, 1); 
+			
+			/* Copy frame without CRC */
+			if ( idev->io.baudrate < 4000000) {
+				skb_put( skb, len-2);
+				memcpy( skb->data, idev->rx_buff.head, len-2);
+			} else {
+				skb_put( skb, len-4);
+				memcpy( skb->data, idev->rx_buff.head, len-4);
+			}
+
+			/* Move to next frame */
+			idev->rx_buff.offset += len;
+			idev->rx_buff.head += len;
+			
+			skb->dev = &idev->netdev;
+			skb->mac.raw  = skb->data;
+			skb->protocol = htons(ETH_P_IRDA);
+			netif_rx( skb);
+			idev->stats.rx_packets++;
+		}
+		/* Read next entry in ST_FIFO */
+		switch_bank(iobase, SET5);
+		status = inb( iobase+FS_FO);
+		len = inb( iobase+RFLFL);
+		len |= inb( iobase+RFLFH) << 8;
+	}
+	/* Restore set register */
+	outb( set, iobase+SSR);
+
+	return TRUE;
+}
+
+/*
+ * Function pc87108_pio_receive (idev)
+ *
+ *    Receive all data in receiver FIFO
+ *
+ */
+static void w83977af_pio_receive( struct irda_device *idev) 
+{
+	__u8 byte = 0x00;
+	int iobase;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+	
+	iobase = idev->io.iobase;
+	
+	if ( idev->rx_buff.len == 0) {
+		idev->rx_buff.head = idev->rx_buff.data;
+	}
+
+	/*  Receive all characters in Rx FIFO */
+	do {
+		byte = inb( iobase+RBR);
+		async_unwrap_char( idev, byte);
+
+	} while ( inb( iobase+USR) & USR_RDR); /* Data available */	
+}
+
+/*
+ * Function w83977af_sir_interrupt (idev, eir)
+ *
+ *    Handle SIR interrupt
+ *
+ */
+static __u8 w83977af_sir_interrupt( struct irda_device *idev, int isr)
+{
+	int len;
+	int actual;
+	__u8 new_icr = 0;
+
+	DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr);
+	
+	/* Transmit FIFO low on data */
+	if ( isr & ISR_TXTH_I) {
+		/* Write data left in transmit buffer */
+		len = idev->tx_buff.len - idev->tx_buff.offset;
+
+		ASSERT( len > 0, return 0;);
+		actual = w83977af_pio_write( idev->io.iobase, 
+					     idev->tx_buff.head, 
+					     len, idev->io.fifo_size);
+		idev->tx_buff.offset += actual;
+		idev->tx_buff.head += actual;
+		
+		idev->io.direction = IO_XMIT;
+		ASSERT( actual <= len, return 0;);
+		/* Check if finished */
+		if ( actual == len) { 
+			DEBUG( 4, __FUNCTION__ "(), finished with frame!\n");
+			idev->netdev.tbusy = 0; /* Unlock */
+			idev->stats.tx_packets++;
+
+			/* Schedule network layer */
+		        mark_bh(NET_BH);	
+
+			new_icr |= ICR_ETBREI;
+		} else
+			new_icr |= ICR_ETXTHI;
+	}
+	/* Check if transmission has completed */
+	if ( isr & ISR_TXEMP_I) {
+		
+		/* Turn around and get ready to receive some data */
+		idev->io.direction = IO_RECV;
+		new_icr |= ICR_ERBRI;
+	}
+
+	/* Rx FIFO threshold or timeout */
+	if ( isr & ISR_RXTH_I) {
+		w83977af_pio_receive( idev);
+
+		/* Keep receiving */
+		new_icr |= ICR_ERBRI;
+	}
+	return new_icr;
+}
+
+/*
+ * Function pc87108_fir_interrupt (idev, eir)
+ *
+ *    Handle MIR/FIR interrupt
+ *
+ */
+static __u8 w83977af_fir_interrupt( struct irda_device *idev, int isr)
+{
+	__u8 new_icr = 0;
+	__u8 set;
+	int iobase;
+
+	DEBUG( 4, __FUNCTION__ "(), isr=%#x\n", isr);
+
+	iobase = idev->io.iobase;
+
+	set = inb( iobase+SSR);
+	
+	/* End of frame detected in FIFO */
+	if ( isr & (ISR_FEND_I|ISR_FSF_I)) {
+		if ( w83977af_dma_receive_complete( idev)) {
+			
+			new_icr |= ICR_EFSFI;
+		} else {
+			/* DMA not finished yet */
+
+			/* Set timer value, resolution 1 ms */
+			switch_bank( iobase, SET4);
+			outb( 0x01, iobase+TMRL); /* 1 ms */
+			outb( 0x00, iobase+TMRH);
+
+			/* Start timer */
+			outb( IR_MSL_EN_TMR, iobase+IR_MSL);
+
+			new_icr |= ICR_ETMRI;
+		}
+	}
+	/* Timer finished */
+	if ( isr & ISR_TMR_I) {
+		/* Disable timer */
+		switch_bank( iobase, SET4);
+		outb( 0, iobase+IR_MSL);
+
+		/* Clear timer event */
+		/* switch_bank(iobase, SET0); */
+/* 		outb( ASCR_CTE, iobase+ASCR); */
+
+		/* Check if this is a TX timer interrupt */
+		if ( idev->io.direction == IO_XMIT) {
+			w83977af_dma_write( idev, iobase);
+
+			new_icr |= ICR_EDMAI;
+		} else {
+			/* Check if DMA has now finished */
+			w83977af_dma_receive_complete( idev);
+
+			new_icr |= ICR_EFSFI;
+		}
+	}	
+	/* Finished with DMA */
+	if ( isr & ISR_DMA_I) {
+		w83977af_dma_xmit_complete( idev);
+
+		/* Check if there are more frames to be transmitted */
+		if ( irda_device_txqueue_empty( idev)) {
+		
+			/* Prepare for receive */
+			w83977af_dma_receive( idev);
+			new_icr = ICR_EFSFI;
+		}
+	}
+	
+	/* Restore set */
+	outb( set, iobase+SSR);
+
+	return new_icr;
+}
+
+/*
+ * Function pc87108_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	__u8 set, icr, isr;
+	int iobase;
+
+	struct irda_device *idev = (struct irda_device *) dev_id;
+
+	if ( idev == NULL) {
+		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
+			driver_name, irq);
+		return;
+	}
+
+	idev->netdev.interrupt = 1;
+
+	iobase = idev->io.iobase;
+
+	/* Save current bank */
+	set = inb( iobase+SSR);
+	switch_bank( iobase, SET0);
+	
+	icr = inb( iobase+ICR); 
+	isr = inb( iobase+ISR) & icr; /* Mask out the interesting ones */ 
+
+	outb( 0, iobase+ICR); /* Disable interrupts */
+	
+	if ( isr) {
+		/* Dispatch interrupt handler for the current speed */
+		if ( idev->io.baudrate > 115200)
+			icr = w83977af_fir_interrupt( idev, isr);
+		else
+			icr = w83977af_sir_interrupt( idev, isr);
+	}
+
+	outb( icr, iobase+ICR);    /* Restore (new) interrupts */
+	outb( set, iobase+SSR);    /* Restore bank register */
+
+	idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function w83977af_wait_until_sent (idev)
+ *
+ *    This function should put the current thread to sleep until all data 
+ *    have been sent, so it is safe to f.eks. change the speed.
+ */
+static void w83977af_wait_until_sent( struct irda_device *idev)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(6);
+}
+
+/*
+ * Function w83977af_is_receiving (idev)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int w83977af_is_receiving( struct irda_device *idev)
+{
+	int status = FALSE;
+	int iobase;
+	__u8 set;
+
+	ASSERT( idev != NULL, return FALSE;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+	if ( idev->io.baudrate > 115200) {
+		iobase = idev->io.iobase;
+
+		/* Check if rx FIFO is not empty */
+		set = inb( iobase+SSR);
+		switch_bank( iobase, SET2);
+		if (( inb( iobase+RXFDTH) & 0x3f) != 0) {
+			/* We are receiving something */
+			status =  TRUE;
+		}
+		outb( set, iobase+SSR);
+	} else 
+		status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+	
+	return status;
+}
+
+/*
+ * Function w83977af_net_init (dev)
+ *
+ *    
+ *
+ */
+static int w83977af_net_init( struct device *dev)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	/* Set up to be a normal IrDA network device driver */
+	irda_device_setup( dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+
+/*
+ * Function w83977af_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int w83977af_net_open( struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	__u8 set;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	ASSERT( dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+	
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	
+	iobase = idev->io.iobase;
+
+	if (request_irq( idev->io.irq, w83977af_interrupt, 0, idev->name, 
+			 (void *) idev)) {
+		return -EAGAIN;
+	}
+	/*
+	 * Always allocate the DMA channel after the IRQ,
+	 * and clean up on failure.
+	 */
+	if (request_dma(idev->io.dma, idev->name)) {
+		free_irq( idev->io.irq, idev);
+		return -EAGAIN;
+	}
+		
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+
+ 	/* Enable some interrupts so we can receive frames again */
+ 	switch_bank(iobase, SET0);
+ 	if ( idev->io.baudrate > 115200) {
+ 		outb( ICR_EFSFI, iobase+ICR);
+ 		w83977af_dma_receive( idev);
+ 	} else
+ 		outb( ICR_ERBRI, iobase+ICR);
+
+	/* Restore bank register */
+	outb( set, iobase+SSR);
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function w83977af_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int w83977af_net_close(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	__u8 set;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	ASSERT( dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+	
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	
+	iobase = idev->io.iobase;
+
+	disable_dma( idev->io.dma);
+
+	/* Save current set */
+	set = inb( iobase+SSR);
+	
+	/* Disable interrupts */
+	switch_bank( iobase, SET0);
+	outb( 0, iobase+ICR); 
+
+	free_irq( idev->io.irq, idev);
+	free_dma( idev->io.dma);
+
+	/* Restore bank register */
+	outb( set, iobase+SSR);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *    
+ *
+ */
+int init_module(void)
+{
+	w83977af_init();
+
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    
+ *
+ */
+void cleanup_module(void)
+{
+	w83977af_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v2.1.131/linux/drivers/net/lance.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/lance.c	Fri Dec 18 09:37:40 1998
@@ -1,6 +1,6 @@
-/* lance.c: An AMD LANCE ethernet driver for linux. */
+/* lance.c: An AMD LANCE/PCnet ethernet driver for Linux. */
 /*
-	Written 1993,1994,1995 by Donald Becker.
+	Written/copyright 1993-1998 by Donald Becker.
 
 	Copyright 1993 United States Government as represented by the
 	Director, National Security Agency.
@@ -8,13 +8,12 @@
 	of the GNU Public License, incorporated herein by reference.
 
 	This driver is for the Allied Telesis AT1500 and HP J2405A, and should work
-	with most other LANCE-based bus-master (NE2100 clone) ethercards.
+	with most other LANCE-based bus-master (NE2100/NE2500) ethercards.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
 	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
 
-
 	Fixing alignment problem with 1.3.* kernel and some minor changes
 	by Andrey V. Savochkin, 1996.
 
@@ -28,14 +27,28 @@
 	But I should to inform you that I'm not an expert in the LANCE card
 	and it may occurs that you will receive no answer on your mail
 	to Donald Becker. I didn't receive any answer on all my letters
-	to him. Who knows why... But may be you are more lucky?  ;-)
+	to him. Who knows why... But may be you are more lucky?  ;->
                                                           SAW
-    Fixed 7990 autoIRQ failure and reversed unneeded alignment. 8/20/96 djb
+
+	Thomas Bogendoerfer (tsbogend@bigbug.franken.de):
+	- added support for Linux/Alpha, but removed most of it, because
+        it worked only for the PCI chip. 
+      - added hook for the 32bit lance driver
+      - added PCnetPCI II (79C970A) to chip table
+	Paul Gortmaker (gpg109@rsphy1.anu.edu.au):
+	- hopefully fix above so Linux/Alpha can use ISA cards too.
+    8/20/96 Fixed 7990 autoIRQ failure and reversed unneeded alignment -djb
+    v1.12 10/27/97 Module support -djb
+    v1.14  2/3/98 Module support modified, made PCI support optional -djb
+    
+    Forward ported v1.14 to 2.1.129, merged the PCI and misc changes from
+    the 2.1 version of the old driver - Alan Cox
 */
 
-static const char *version = "lance.c:v1.09 Aug 20 1996 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
+static const char *version = "lance.c:v1.14ac 1998/11/20 dplatt@3do.com, becker@cesdis.gsfc.nasa.gov\n";
 
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -54,13 +67,9 @@
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 
-static unsigned int lance_portlist[] __initdata = {0x300, 0x320, 0x340, 0x360, 0};
-void lance_probe1(int ioaddr);
-
-#ifdef HAVE_DEVLIST
-struct netdev_entry lance_drv =
-{"lance", lance_probe1, LANCE_TOTAL_SIZE, lance_portlist};
-#endif
+static unsigned int lance_portlist[] __initdata = { 0x300, 0x320, 0x340, 0x360, 0};
+int lance_probe(struct device *dev);
+int lance_probe1(struct device *dev, int ioaddr, int irq, int options);
 
 #ifdef LANCE_DEBUG
 int lance_debug = LANCE_DEBUG;
@@ -96,7 +105,7 @@
 probed for by enabling each free DMA channel in turn and checking if
 initialization succeeds.
 
-The HP-J2405A board is an exception: with this board it's easy to read the
+The HP-J2405A board is an exception: with this board it is easy to read the
 EEPROM-set values for the base, IRQ, and DMA.  (Of course you must already
 _know_ the base address -- that field is for writing the EEPROM.)
 
@@ -147,36 +156,19 @@
 the 'lp->tx_full' flag.
 
 The interrupt handler has exclusive control over the Rx ring and records stats
-from the Tx ring.  (The Tx-done interrupt can't be selectively turned off, so
+from the Tx ring. (The Tx-done interrupt can't be selectively turned off, so
 we can't avoid the interrupt overhead by having the Tx routine reap the Tx
 stats.)	 After reaping the stats, it marks the queue entry as empty by setting
-the 'base' to zero.	 Iff the 'lp->tx_full' flag is set, it clears both the
+the 'base' to zero. Iff the 'lp->tx_full' flag is set, it clears both the
 tx_full and tbusy flags.
 
 */
 
-/* Memory accessed from LANCE card must be aligned on 8-byte boundaries.
-   But we can't believe that kmalloc()'ed memory satisfies it. -- SAW */
-#define LANCE_KMALLOC(x) \
-	((void *) (((unsigned long)kmalloc((x)+7, GFP_DMA | GFP_KERNEL)+7) & ~7))
-
-/*
- * Changes:
- *	Thomas Bogendoerfer (tsbogend@alpha.franken.de):
- *	- added support for Linux/Alpha, but removed most of it, because
- *        it worked only for the PCI chip. 
- *      - added hook for the 32bit lance driver
- *      - added PCnetPCI II (79C970A) to chip table
- *      - made 32bit driver standalone
- *      - changed setting of autoselect bit
- *
- *	Paul Gortmaker (gpg109@rsphy1.anu.edu.au):
- *	- hopefully fix above so Linux/Alpha can use ISA cards too.
- */
-
 /* Set the number of Tx and Rx buffers, using Log_2(# buffers).
    Reasonable default values are 16 Tx buffers, and 16 Rx buffers.
-   That translates to 4 and 4 (16 == 2^^4). */
+   That translates to 4 and 4 (16 == 2^^4).
+   This is a compile-time option for efficiency.
+   */
 #ifndef LANCE_LOG_TX_BUFFERS
 #define LANCE_LOG_TX_BUFFERS 4
 #define LANCE_LOG_RX_BUFFERS 4
@@ -230,6 +222,8 @@
 	const char *name;
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
 	struct sk_buff* tx_skbuff[TX_RING_SIZE];
+	/* The addresses of receive-in-place skbuffs. */
+	struct sk_buff* rx_skbuff[RX_RING_SIZE];
 	unsigned long rx_buffs;		/* Address of Rx and Tx buffers. */
 	/* Tx low-memory "bounce buffer" address. */
 	char (*tx_bounce_buffs)[PKT_BUF_SZ];
@@ -247,7 +241,6 @@
 #define LANCE_MUST_REINIT_RING  0x00000004
 #define LANCE_MUST_UNRESET      0x00000008
 #define LANCE_HAS_MISSED_FRAME  0x00000010
-#define PCNET32_POSSIBLE        0x00000020
 
 /* A mapping from the chip ID number to the part number and features.
    These are from the datasheets -- in real life the '970 version
@@ -267,21 +260,15 @@
 			LANCE_HAS_MISSED_FRAME},
 	{0x2420, "PCnet/PCI 79C970",		/* 79C970 or 79C974 PCnet-SCSI, PCI. */
 		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
-			LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
+			LANCE_HAS_MISSED_FRAME},
 	/* Bug: the PCnet/PCI actually uses the PCnet/VLB ID number, so just call
 		it the PCnet32. */
 	{0x2430, "PCnet32",					/* 79C965 PCnet for VL bus. */
 		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
-			LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
+			LANCE_HAS_MISSED_FRAME},
         {0x2621, "PCnet/PCI-II 79C970A",        /* 79C970A PCInetPCI II. */
                 LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
-                        LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
-        {0x2623, "PCnet/FAST 79C971",        /* 79C971 PCInetFAST. */
-                LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
-                        LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
-        {0x2624, "PCnet/FAST+ 79C972",       /* 79C972 PCInetFAST+. */
-                LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
-                        LANCE_HAS_MISSED_FRAME + PCNET32_POSSIBLE},
+                        LANCE_HAS_MISSED_FRAME},
 	{0x0, 	 "PCnet (unknown)",
 		LANCE_ENABLE_AUTOSELECT + LANCE_MUST_REINIT_RING +
 			LANCE_HAS_MISSED_FRAME},
@@ -298,7 +285,7 @@
 
 static int lance_open(struct device *dev);
 static int lance_open_fail(struct device *dev);
-static void lance_init_ring(struct device *dev);
+static void lance_init_ring(struct device *dev, int mode);
 static int lance_start_xmit(struct sk_buff *skb, struct device *dev);
 static int lance_rx(struct device *dev);
 static void lance_interrupt(int irq, void *dev_id, struct pt_regs *regs);
@@ -308,24 +295,83 @@
 
 
 
-/* This lance probe is unlike the other board probes in 1.0.*.  The LANCE may
-   have to allocate a contiguous low-memory region for bounce buffers.
-   This requirement is satisfied by having the lance initialization occur
-   before the memory management system is started, and thus well before the
-   other probes. */
+#ifdef MODULE
+#define MAX_CARDS		8	/* Max number of interfaces (cards) per module */
+#define IF_NAMELEN		8	/* # of chars for storing dev->name */
+
+static int io[MAX_CARDS] = { 0, };
+static int dma[MAX_CARDS] = { 0, };
+static int irq[MAX_CARDS]  = { 0, };
+
+static char ifnames[MAX_CARDS][IF_NAMELEN] = { {0, }, };
+static struct device dev_lance[MAX_CARDS] =
+{{
+    0, /* device name is inserted by linux/drivers/net/net_init.c */
+	0, 0, 0, 0,
+	0, 0,
+	0, 0, 0, NULL, NULL}};
+
+int init_module(void)
+{
+	int this_dev, found = 0;
+
+	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
+		struct device *dev = &dev_lance[this_dev];
+		dev->name = ifnames[this_dev];
+		dev->irq = irq[this_dev];
+		dev->base_addr = io[this_dev];
+		dev->dma = dma[this_dev];
+		dev->init = lance_probe;
+		if (io[this_dev] == 0)  {
+			if (this_dev != 0) break; /* only complain once */
+			printk(KERN_NOTICE "lance.c: Module autoprobing not allowed. Append \"io=0xNNN\" value(s).\n");
+			return -EPERM;
+		}
+		if (register_netdev(dev) != 0) {
+			printk(KERN_WARNING "lance.c: No PCnet/LANCE card found (i/o = 0x%x).\n", io[this_dev]);
+			if (found != 0) return 0;	/* Got at least one. */
+			return -ENXIO;
+		}
+		found++;
+	}
+
+	return 0;
+}
+
+void cleanup_module(void)
+{
+	int this_dev;
+
+	for (this_dev = 0; this_dev < MAX_CARDS; this_dev++) {
+		struct device *dev = &dev_lance[this_dev];
+		if (dev->priv != NULL) {
+			kfree(dev->priv);
+			dev->priv = NULL;
+			free_dma(dev->dma);
+			release_region(dev->base_addr, LANCE_TOTAL_SIZE);
+			unregister_netdev(dev);
+		}
+	}
+}
+#endif /* MODULE */
 
-__initfunc(int lance_init(void))
+/* Starting in v2.1.*, the LANCE/PCnet probe is now similar to the other
+   board probes now that kmalloc() can allocate ISA DMA-able regions.
+   This also allows the LANCE driver to be used as a module.
+   */
+int lance_probe(struct device *dev)
 {
-	int *port;
+	int *port, result;
 
-	if (virt_to_bus(high_memory) <= 16*1024*1024)
+	if (high_memory <= 16*1024*1024)
 		lance_need_isa_bounce_buffers = 0;
 
-#if defined(CONFIG_PCI) && !(defined(CONFIG_PCNET32) || defined(CONFIG_PCNET32_MODULE))
+#if defined(CONFIG_PCI)
     if (pci_present()) {
-	    struct pci_dev *pdev = NULL;
+		struct pci_dev *pdev = NULL;
 		if (lance_debug > 1)
-			printk("lance.c: PCI is present, checking for devices...\n");
+			printk("lance.c: PCI bios is present, checking for devices...\n");
+
 		while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE, pdev))) {
 			unsigned int pci_ioaddr;
 			unsigned short pci_command;
@@ -344,8 +390,9 @@
 			}
 			printk("Found PCnet/PCI at %#x, irq %d.\n",
 				   pci_ioaddr, pci_irq_line);
-			lance_probe1(pci_ioaddr);
+			result = lance_probe1(dev, pci_ioaddr, pci_irq_line, 0);
 			pci_irq_line = 0;
+			if (!result) return 0;
 		}
 	}
 #endif  /* defined(CONFIG_PCI) */
@@ -359,16 +406,17 @@
 			char offset15, offset14 = inb(ioaddr + 14);
 			
 			if ((offset14 == 0x52 || offset14 == 0x57) &&
-				((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44))
-				lance_probe1(ioaddr);
+				((offset15 = inb(ioaddr + 15)) == 0x57 || offset15 == 0x44)) {
+				result = lance_probe1(dev, ioaddr, 0, 0);
+				if ( !result ) return 0;
+			}
 		}
 	}
-	return 0;
+	return -ENODEV;
 }
 
-__initfunc(void lance_probe1(int ioaddr))
+__initfunc(int lance_probe1(struct device *dev, int ioaddr, int irq, int options))
 {
-	struct device *dev;
 	struct lance_private *lp;
 	short dma_channels;					/* Mark spuriously-busy DMA channels */
 	int i, reset_val, lance_version;
@@ -406,7 +454,7 @@
 
 	outw(0x0000, ioaddr+LANCE_ADDR); /* Switch to window 0 */
 	if (inw(ioaddr+LANCE_DATA) != 0x0004)
-		return;
+		return -ENODEV;
 
 	/* Get the version of the chip. */
 	outw(88, ioaddr+LANCE_ADDR);
@@ -419,24 +467,17 @@
 		if (lance_debug > 2)
 			printk("  LANCE chip version is %#x.\n", chip_version);
 		if ((chip_version & 0xfff) != 0x003)
-			return;
+			return -ENODEV;
 		chip_version = (chip_version >> 12) & 0xffff;
 		for (lance_version = 1; chip_table[lance_version].id_number; lance_version++) {
 			if (chip_table[lance_version].id_number == chip_version)
 				break;
 		}
 	}
-    
-#if defined(CONFIG_PCNET32) || defined (CONFIG_PCNET32_MODULE)
-        /*
-	 * if pcnet32 is configured and the chip is capable of 32bit mode
-	 * leave the card alone
-	 */
-        if (chip_table[lance_version].flags & PCNET32_POSSIBLE)
-          return;
-#endif    
 
-	dev = init_etherdev(0, 0);
+	/* We can't use init_etherdev() to allocate dev->priv because it must
+	   a ISA DMA-able region. */
+	dev = init_etherdev(dev, 0);
 	dev->open = lance_open_fail;
 	chipname = chip_table[lance_version].name;
 	printk("%s: %s at %#3x,", dev->name, chipname, ioaddr);
@@ -450,6 +491,7 @@
 	request_region(ioaddr, LANCE_TOTAL_SIZE, chip_table[lance_version].name);
 
 	/* Make certain the data structures used by the LANCE are aligned and DMAble. */
+		
 	lp = (struct lance_private *)(((unsigned long)kmalloc(sizeof(*lp)+7,
 										   GFP_DMA | GFP_KERNEL)+7) & ~7);
 	if (lance_debug > 6) printk(" (#0x%05lx)", (unsigned long)lp);
@@ -483,9 +525,9 @@
 	outw(0x0000, ioaddr+LANCE_ADDR);
 	inw(ioaddr+LANCE_ADDR);
 
-	if (pci_irq_line) {
+	if (irq) {					/* Set iff PCI card. */
 		dev->dma = 4;			/* Native bus-master, no DMA channel needed. */
-		dev->irq = pci_irq_line;
+		dev->irq = irq;
 	} else if (hp_builtin) {
 		static const char dma_tbl[4] = {3, 5, 6, 0};
 		static const char irq_tbl[4] = {3, 4, 5, 9};
@@ -534,7 +576,7 @@
 			printk(", probed IRQ %d", dev->irq);
 		else {
 			printk(", failed to detect IRQ line.\n");
-			return;
+			return -ENODEV;
 		}
 
 		/* Check for the initialization done bit, 0x0100, which means
@@ -548,7 +590,7 @@
 	} else if (dev->dma) {
 		if (request_dma(dev->dma, chipname)) {
 			printk("DMA %d allocation failed.\n", dev->dma);
-			return;
+			return -ENODEV;
 		} else
 			printk(", assigned DMA %d.\n", dev->dma);
 	} else {			/* OK, we have to auto-DMA. */
@@ -588,7 +630,7 @@
 		}
 		if (i == 4) {			/* Failure: bail. */
 			printk("DMA detection failed.\n");
-			return;
+			return -ENODEV;
 		}
 	}
 
@@ -601,7 +643,7 @@
 		dev->irq = autoirq_report(4);
 		if (dev->irq == 0) {
 			printk("  Failed to detect the 7990 IRQ line.\n");
-			return;
+			return -ENODEV;
 		}
 		printk("  Auto-IRQ detected IRQ%d.\n", dev->irq);
 	}
@@ -610,8 +652,8 @@
 		/* Turn on auto-select of media (10baseT or BNC) so that the user
 		   can watch the LEDs even if the board isn't opened. */
 		outw(0x0002, ioaddr+LANCE_ADDR);
-		/* set autoselect and clean xmausel */
-		outw((inw(ioaddr+LANCE_BUS_IF) & 0xfffe) | 0x0002, ioaddr+LANCE_BUS_IF);
+		/* Don't touch 10base2 power bit. */
+		outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
 	}
 
 	if (lance_debug > 0  &&  did_version++ == 0)
@@ -624,7 +666,7 @@
 	dev->get_stats = lance_get_stats;
 	dev->set_multicast_list = set_multicast_list;
 
-	return;
+	return 0;
 }
 
 static int
@@ -647,6 +689,8 @@
 		return -EAGAIN;
 	}
 
+	MOD_INC_USE_COUNT;
+
 	/* We used to allocate DMA here, but that was silly.
 	   DMA lines can't be shared!  We now permanently allocate them. */
 
@@ -668,9 +712,9 @@
 	if (chip_table[lp->chip_version].flags & LANCE_ENABLE_AUTOSELECT) {
 		/* This is 79C960-specific: Turn on auto-select of media (AUI, BNC). */
 		outw(0x0002, ioaddr+LANCE_ADDR);
-		/* set autoselect and clean xmausel */
-		outw((inw(ioaddr+LANCE_BUS_IF) & 0xfffe) | 0x0002, ioaddr+LANCE_BUS_IF);
-	}
+		/* Only touch autoselect bit. */
+		outw(inw(ioaddr+LANCE_BUS_IF) | 0x0002, ioaddr+LANCE_BUS_IF);
+ 	}
 
 	if (lance_debug > 1)
 		printk("%s: lance_open() irq %d dma %d tx/rx rings %#x/%#x init %#x.\n",
@@ -679,7 +723,7 @@
 		           (u32) virt_to_bus(lp->rx_ring),
 			   (u32) virt_to_bus(&lp->init_block));
 
-	lance_init_ring(dev);
+	lance_init_ring(dev, GFP_KERNEL);
 	/* Re-initialize the LANCE, and start it when done. */
 	outw(0x0001, ioaddr+LANCE_ADDR);
 	outw((short) (u32) virt_to_bus(&lp->init_block), ioaddr+LANCE_DATA);
@@ -741,7 +785,7 @@
 
 /* Initialize the LANCE Rx and Tx rings. */
 static void
-lance_init_ring(struct device *dev)
+lance_init_ring(struct device *dev, int gfp)
 {
 	struct lance_private *lp = (struct lance_private *)dev->priv;
 	int i;
@@ -751,12 +795,26 @@
 	lp->dirty_rx = lp->dirty_tx = 0;
 
 	for (i = 0; i < RX_RING_SIZE; i++) {
-		lp->rx_ring[i].base = (u32)virt_to_bus((char *)lp->rx_buffs + i*PKT_BUF_SZ) | 0x80000000;
+		struct sk_buff *skb;
+		void *rx_buff;
+
+		skb = alloc_skb(PKT_BUF_SZ, GFP_DMA | gfp);
+		lp->rx_skbuff[i] = skb;
+		if (skb) {
+			skb->dev = dev;
+			rx_buff = skb->tail;
+		} else
+			rx_buff = kmalloc(PKT_BUF_SZ, GFP_DMA | gfp);
+		if (rx_buff == NULL)
+			lp->rx_ring[i].base = 0;
+		else
+			lp->rx_ring[i].base = (u32)virt_to_bus(rx_buff) | 0x80000000;
 		lp->rx_ring[i].buf_length = -PKT_BUF_SZ;
 	}
 	/* The Tx buffer address is filled in as needed, but we do need to clear
 	   the upper ownership bit. */
 	for (i = 0; i < TX_RING_SIZE; i++) {
+		lp->tx_skbuff[i] = 0;
 		lp->tx_ring[i].base = 0;
 	}
 
@@ -777,7 +835,7 @@
 	if (must_reinit ||
 		(chip_table[lp->chip_version].flags & LANCE_MUST_REINIT_RING)) {
 		lance_purge_tx_ring(dev);
-		lance_init_ring(dev);
+		lance_init_ring(dev, GFP_ATOMIC);
 	}
 	outw(0x0000,    dev->base_addr + LANCE_ADDR);
 	outw(csr0_bits, dev->base_addr + LANCE_DATA);
@@ -872,14 +930,14 @@
 		memcpy(&lp->tx_bounce_buffs[entry], skb->data, skb->len);
 		lp->tx_ring[entry].base =
 			((u32)virt_to_bus((lp->tx_bounce_buffs + entry)) & 0xffffff) | 0x83000000;
-		dev_kfree_skb (skb);
+		dev_kfree_skb(skb);
 	} else {
 		lp->tx_skbuff[entry] = skb;
 		lp->tx_ring[entry].base = ((u32)virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
 	}
 	lp->cur_tx++;
-	lp->stats.tx_bytes+=skb->len;
-	
+	lp->stats.tx_bytes += skb->len;
+
 	/* Trigger an immediate send poll. */
 	outw(0x0000, ioaddr+LANCE_ADDR);
 	outw(0x0048, ioaddr+LANCE_DATA);
@@ -915,7 +973,7 @@
 	ioaddr = dev->base_addr;
 	lp = (struct lance_private *)dev->priv;
 	if (dev->interrupt)
-		printk("%s: Re-entering the interrupt handler.\n", dev->name);
+		printk(KERN_WARNING "%s: Re-entering the interrupt handler.\n", dev->name);
 
 	dev->interrupt = 1;
 
@@ -1110,6 +1168,7 @@
 {
 	int ioaddr = dev->base_addr;
 	struct lance_private *lp = (struct lance_private *)dev->priv;
+	int i;
 
 	dev->start = 0;
 	dev->tbusy = 1;
@@ -1134,9 +1193,23 @@
 		disable_dma(dev->dma);
 		release_dma_lock(flags);
 	}
-
 	free_irq(dev->irq, dev);
 
+	/* Free all the skbuffs in the Rx and Tx queues. */
+	for (i = 0; i < RX_RING_SIZE; i++) {
+		struct sk_buff *skb = lp->rx_skbuff[i];
+		lp->rx_skbuff[i] = 0;
+		lp->rx_ring[i].base = 0;		/* Not owned by LANCE chip. */
+		if (skb)
+			dev_kfree_skb(skb);
+	}
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		if (lp->tx_skbuff[i])
+			dev_kfree_skb(lp->tx_skbuff[i]);
+		lp->tx_skbuff[i] = 0;
+	}
+
+	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -1195,11 +1268,3 @@
 
 }
 
-
-/*
- * Local variables:
- *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c lance.c"
- *  c-indent-level: 4
- *  tab-width: 4
- * End:
- */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/lne390.c linux/drivers/net/lne390.c
--- v2.1.131/linux/drivers/net/lne390.c	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/lne390.c	Wed Dec 16 13:35:49 1998
@@ -430,7 +430,6 @@
 			release_region(dev->base_addr, LNE390_IO_EXTENT);
 			if (ei_status.reg0)
 				iounmap((void *)dev->mem_start);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ltpc.c linux/drivers/net/ltpc.c
--- v2.1.131/linux/drivers/net/ltpc.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/net/ltpc.c	Wed Dec 16 13:35:49 1998
@@ -1059,14 +1059,14 @@
 
 	inb_p(io+1);
 	inb_p(io+0);
-	timeout = jiffies+100;
-	while(timeout>jiffies) {
+	timeout = jiffies+100*HZ/100;
+	while(time_before(jiffies, timeout)) {
 		if ( 0xfa == inb_p(io+6) ) break;
 	}
 
 	inb_p(io+3);
 	inb_p(io+2);
-	while(timeout>jiffies) {
+	while(time_before(jiffies, timeout)) {
 		if ( 0xfb == inb_p(io+6) ) break;
 	}
 
@@ -1161,8 +1161,8 @@
 
 	inb_p(io+1);
 	inb_p(io+3);
-	timeout = jiffies+2;
-	while(timeout>jiffies) ; /* hold it in reset for a coupla jiffies */
+	timeout = jiffies+2*HZ/100;
+	while(time_before(jiffies, timeout)) ; /* hold it in reset for a coupla jiffies */
 	inb_p(io+0);
 	inb_p(io+2);
 	inb_p(io+7); /* clear reset */
@@ -1171,9 +1171,9 @@
 	inb_p(io+5); /* enable dma */
 	inb_p(io+6); /* tri-state interrupt line */
 
-	timeout = jiffies+100;
+	timeout = jiffies+100*HZ/100;
 	
-	while(timeout>jiffies) {
+	while(time_before(jiffies, timeout)) {
 		/* wait for the card to complete initialization */
 	}
  
@@ -1220,8 +1220,8 @@
 
 	(void) inb_p(io+3);
 	(void) inb_p(io+2);
-	timeout = jiffies+100;
-	while(timeout>jiffies) {
+	timeout = jiffies+100*HZ/100;
+	while(time_before(jiffies, timeout)) {
 		if( 0xf9 == inb_p(io+6)) break;
 	}
 
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.1.131/linux/drivers/net/ne.c	Tue Jul 21 00:15:31 1998
+++ linux/drivers/net/ne.c	Wed Dec 16 13:35:49 1998
@@ -68,8 +68,9 @@
 
 /* A zero-terminated list of I/O addresses to be probed at boot. */
 #ifndef MODULE
-static unsigned int netcard_portlist[] __initdata =
-{ 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0};
+static unsigned int netcard_portlist[] __initdata = { 
+	0x300, 0x280, 0x320, 0x340, 0x360, 0x380, 0
+};
 #endif
 
 #ifdef CONFIG_PCI
@@ -85,6 +86,8 @@
 	{PCI_VENDOR_ID_SURECOM,		PCI_DEVICE_ID_SURECOM_NE34,		"SureCom NE34"},
 	{0,}
 };
+
+static int probe_pci = 1;
 #endif
 
 #ifdef SUPPORT_NE_BAD_CLONES
@@ -175,32 +178,32 @@
 
 __initfunc(int ne_probe(struct device *dev))
 {
-    int base_addr = dev ? dev->base_addr : 0;
+	int base_addr = dev ? dev->base_addr : 0;
 
-    /* First check any supplied i/o locations. User knows best. <cough> */
-    if (base_addr > 0x1ff)	/* Check a single specified location. */
-	return ne_probe1(dev, base_addr);
-    else if (base_addr != 0)	/* Don't probe at all. */
-	return ENXIO;
+	/* First check any supplied i/o locations. User knows best. <cough> */
+	if (base_addr > 0x1ff)	/* Check a single specified location. */
+		return ne_probe1(dev, base_addr);
+	else if (base_addr != 0)	/* Don't probe at all. */
+		return ENXIO;
 
 #ifdef CONFIG_PCI
-    /* Then look for any installed PCI clones */
-    if (pci_present() && (ne_probe_pci(dev) == 0))
-	return 0;
+	/* Then look for any installed PCI clones */
+	if (probe_pci && pci_present() && (ne_probe_pci(dev) == 0))
+		return 0;
 #endif
 
 #ifndef MODULE
-    /* Last resort. The semi-risky ISA auto-probe. */
-    for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
-	int ioaddr = netcard_portlist[base_addr];
-	if (check_region(ioaddr, NE_IO_EXTENT))
-	    continue;
-	if (ne_probe1(dev, ioaddr) == 0)
-	    return 0;
-    }
+	/* Last resort. The semi-risky ISA auto-probe. */
+	for (base_addr = 0; netcard_portlist[base_addr] != 0; base_addr++) {
+		int ioaddr = netcard_portlist[base_addr];
+		if (check_region(ioaddr, NE_IO_EXTENT))
+			continue;
+		if (ne_probe1(dev, ioaddr) == 0)
+			return 0;
+	}
 #endif
 
-    return ENODEV;
+	return ENODEV;
 }
 #endif
 
@@ -223,7 +226,7 @@
 		}
 		if (!pdev)
 			continue;
-		printk("ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
+		printk(KERN_INFO "ne.c: PCI BIOS reports %s at i/o %#x, irq %d.\n",
 				pci_clone_list[i].name,
 				pci_ioaddr, pci_irq_line);
 		printk("*\n* Use of the PCI-NE2000 driver with this card is recommended!\n*\n");
@@ -241,61 +244,65 @@
 
 __initfunc(static int ne_probe1(struct device *dev, int ioaddr))
 {
-    int i;
-    unsigned char SA_prom[32];
-    int wordlength = 2;
-    const char *name = NULL;
-    int start_page, stop_page;
-    int neX000, ctron, bad_card;
-    int reg0 = inb_p(ioaddr);
-    static unsigned version_printed = 0;
+	int i;
+	unsigned char SA_prom[32];
+	int wordlength = 2;
+	const char *name = NULL;
+	int start_page, stop_page;
+	int neX000, ctron, copam, bad_card;
+	int reg0 = inb_p(ioaddr);
+	static unsigned version_printed = 0;
 
-    if (reg0 == 0xFF)
-	return ENODEV;
+	if (reg0 == 0xFF)
+		return ENODEV;
+
+	/* Do a preliminary verification that we have a 8390. */
+	{
+		int regd;
+		outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+		regd = inb_p(ioaddr + 0x0d);
+		outb_p(0xff, ioaddr + 0x0d);
+		outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+		inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
+		if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
+			outb_p(reg0, ioaddr);
+			outb_p(regd, ioaddr + 0x0d);	/* Restore the old values. */
+			return ENODEV;
+		}
+	}
+
+	if (load_8390_module("ne.c"))
+		return -ENOSYS;
 
-    /* Do a preliminary verification that we have a 8390. */
-    {	int regd;
-	outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
-	regd = inb_p(ioaddr + 0x0d);
-	outb_p(0xff, ioaddr + 0x0d);
-	outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
-	inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
-	if (inb_p(ioaddr + EN0_COUNTER0) != 0) {
-	    outb_p(reg0, ioaddr);
-	    outb_p(regd, ioaddr + 0x0d);	/* Restore the old values. */
-	    return ENODEV;
-	}
-    }
-
-    if (load_8390_module("ne.c"))
-	return -ENOSYS;
-
-    /* We should have a "dev" from Space.c or the static module table. */
-    if (dev == NULL) {
-	printk(KERN_ERR "ne.c: Passed a NULL device.\n");
-	dev = init_etherdev(0, 0);
-    }
-
-    if (ei_debug  &&  version_printed++ == 0)
-	printk(version);
-
-    printk("NE*000 ethercard probe at %#3x:", ioaddr);
-
-    /* A user with a poor card that fails to ack the reset, or that
-       does not have a valid 0x57,0x57 signature can still use this
-       without having to recompile. Specifying an i/o address along
-       with an otherwise unused dev->mem_end value of "0xBAD" will
-       cause the driver to skip these parts of the probe. */
+	/* We should have a "dev" from Space.c or the static module table. */
+	if (dev == NULL) 
+	{
+		printk(KERN_ERR "ne.c: Passed a NULL device.\n");
+		dev = init_etherdev(0, 0);
+	}
 
-    bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+	if (ei_debug  &&  version_printed++ == 0)
+		printk(version);
 
-    /* Reset card. Who knows what dain-bramaged state it was left in. */
-    {	unsigned long reset_start_time = jiffies;
+	printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr);
 
-	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-	outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+	/* A user with a poor card that fails to ack the reset, or that
+	   does not have a valid 0x57,0x57 signature can still use this
+	   without having to recompile. Specifying an i/o address along
+	   with an otherwise unused dev->mem_end value of "0xBAD" will
+	   cause the driver to skip these parts of the probe. */
 
-	while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
+	bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad));
+
+	/* Reset card. Who knows what dain-bramaged state it was left in. */
+
+	{
+		unsigned long reset_start_time = jiffies;
+
+		/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+		outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET);
+
+		while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0)
 		if (jiffies - reset_start_time > 2*HZ/100) {
 			if (bad_card) {
 				printk(" (warning: no reset ack)");
@@ -305,252 +312,265 @@
 				return ENODEV;
 			}
 		}
+	
+		outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
+	}
 
-	outb_p(0xff, ioaddr + EN0_ISR);		/* Ack all intr. */
-    }
+	/* Read the 16 bytes of station address PROM.
+	   We must first initialize registers, similar to NS8390_init(eifdev, 0).
+	   We can't reliably read the SAPROM address without this.
+	   (I learned the hard way!). */
+	{
+		struct {unsigned char value, offset; } program_seq[] = 
+		{
+			{E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
+			{0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
+			{0x00,	EN0_RCNTLO},	/* Clear the count regs. */
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_IMR},	/* Mask completion irq. */
+			{0xFF,	EN0_ISR},
+			{E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
+			{E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
+			{32,	EN0_RCNTLO},
+			{0x00,	EN0_RCNTHI},
+			{0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
+			{0x00,	EN0_RSARHI},
+			{E8390_RREAD+E8390_START, E8390_CMD},
+		};
 
-    /* Read the 16 bytes of station address PROM.
-       We must first initialize registers, similar to NS8390_init(eifdev, 0).
-       We can't reliably read the SAPROM address without this.
-       (I learned the hard way!). */
-    {
-	struct {unsigned char value, offset; } program_seq[] = {
-	    {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/
-	    {0x48,	EN0_DCFG},	/* Set byte-wide (0x48) access. */
-	    {0x00,	EN0_RCNTLO},	/* Clear the count regs. */
-	    {0x00,	EN0_RCNTHI},
-	    {0x00,	EN0_IMR},	/* Mask completion irq. */
-	    {0xFF,	EN0_ISR},
-	    {E8390_RXOFF, EN0_RXCR},	/* 0x20  Set to monitor */
-	    {E8390_TXOFF, EN0_TXCR},	/* 0x02  and loopback mode. */
-	    {32,	EN0_RCNTLO},
-	    {0x00,	EN0_RCNTHI},
-	    {0x00,	EN0_RSARLO},	/* DMA starting at 0x0000. */
-	    {0x00,	EN0_RSARHI},
-	    {E8390_RREAD+E8390_START, E8390_CMD},
-	};
-	for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
-	    outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
-
-    }
-    for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
-	SA_prom[i] = inb(ioaddr + NE_DATAPORT);
-	SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
-	if (SA_prom[i] != SA_prom[i+1])
-	    wordlength = 1;
-    }
-
-    /*	At this point, wordlength *only* tells us if the SA_prom is doubled
-	up or not because some broken PCI cards don't respect the byte-wide
-	request in program_seq above, and hence don't have doubled up values.
-	These broken cards would otherwise be detected as an ne1000.  */
-
-    if (wordlength == 2)
-	for (i = 0; i < 16; i++)
-		SA_prom[i] = SA_prom[i+i];
-
-    if (pci_irq_line || ioaddr >= 0x400)
-	wordlength = 2;		/* Catch broken PCI cards mentioned above. */
-
-    if (wordlength == 2) {
-	/* We must set the 8390 for word mode. */
-	outb_p(0x49, ioaddr + EN0_DCFG);
-	start_page = NESM_START_PG;
-	stop_page = NESM_STOP_PG;
-    } else {
-	start_page = NE1SM_START_PG;
-	stop_page = NE1SM_STOP_PG;
-    }
-
-    neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
-    ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
-
-    /* Set up the rest of the parameters. */
-    if (neX000 || bad_card) {
-	name = (wordlength == 2) ? "NE2000" : "NE1000";
-    } else if (ctron) {
-	name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
-	start_page = 0x01;
-	stop_page = (wordlength == 2) ? 0x40 : 0x20;
-    } else {
-#ifdef SUPPORT_NE_BAD_CLONES
-	/* Ack!  Well, there might be a *bad* NE*000 clone there.
-	   Check for total bogus addresses. */
-	for (i = 0; bad_clone_list[i].name8; i++) {
-	    if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
-		SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
-		SA_prom[2] == bad_clone_list[i].SAprefix[2]) {
-		if (wordlength == 2) {
-		    name = bad_clone_list[i].name16;
-		} else {
-		    name = bad_clone_list[i].name8;
-		}
-		break;
-	    }
-	}
-	if (bad_clone_list[i].name8 == NULL) {
-	    printk(" not found (invalid signature %2.2x %2.2x).\n",
-		   SA_prom[14], SA_prom[15]);
-	    return ENXIO;
+		for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++)
+			outb_p(program_seq[i].value, ioaddr + program_seq[i].offset);
+
+	}
+	for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) {
+		SA_prom[i] = inb(ioaddr + NE_DATAPORT);
+		SA_prom[i+1] = inb(ioaddr + NE_DATAPORT);
+		if (SA_prom[i] != SA_prom[i+1])
+			wordlength = 1;
+	}
+
+	/* At this point, wordlength *only* tells us if the SA_prom is doubled
+	   up or not because some broken PCI cards don't respect the byte-wide
+	   request in program_seq above, and hence don't have doubled up values.
+	   These broken cards would otherwise be detected as an ne1000.  */
+
+	if (wordlength == 2)
+		for (i = 0; i < 16; i++)
+			SA_prom[i] = SA_prom[i+i];
+
+	if (pci_irq_line || ioaddr >= 0x400)
+		wordlength = 2;		/* Catch broken PCI cards mentioned above. */
+
+	if (wordlength == 2) 
+	{
+		/* We must set the 8390 for word mode. */
+		outb_p(0x49, ioaddr + EN0_DCFG);
+		start_page = NESM_START_PG;
+		stop_page = NESM_STOP_PG;
+	} else {
+		start_page = NE1SM_START_PG;
+		stop_page = NE1SM_STOP_PG;
+	}
+
+	neX000 = (SA_prom[14] == 0x57  &&  SA_prom[15] == 0x57);
+	ctron =  (SA_prom[0] == 0x00 && SA_prom[1] == 0x00 && SA_prom[2] == 0x1d);
+	copam =  (SA_prom[14] == 0x49 && SA_prom[15] == 0x00);
+	
+
+	/* Set up the rest of the parameters. */
+	if (neX000 || bad_card || copam) {
+		name = (wordlength == 2) ? "NE2000" : "NE1000";
+	}
+	else if (ctron) 
+	{
+		name = (wordlength == 2) ? "Ctron-8" : "Ctron-16";
+		start_page = 0x01;
+		stop_page = (wordlength == 2) ? 0x40 : 0x20;
 	}
+	else
+	{
+#ifdef SUPPORT_NE_BAD_CLONES
+		/* Ack!  Well, there might be a *bad* NE*000 clone there.
+		   Check for total bogus addresses. */
+		for (i = 0; bad_clone_list[i].name8; i++) 
+		{
+			if (SA_prom[0] == bad_clone_list[i].SAprefix[0] &&
+				SA_prom[1] == bad_clone_list[i].SAprefix[1] &&
+				SA_prom[2] == bad_clone_list[i].SAprefix[2]) 
+			{
+				if (wordlength == 2) 
+				{
+					name = bad_clone_list[i].name16;
+				} else {
+					name = bad_clone_list[i].name8;
+				}
+				break;
+			}
+		}
+		if (bad_clone_list[i].name8 == NULL) 
+		{
+			printk(" not found (invalid signature %2.2x %2.2x).\n",
+				SA_prom[14], SA_prom[15]);
+			return ENXIO;
+		}
 #else
-	printk(" not found.\n");
-	return ENXIO;
+		printk(" not found.\n");
+		return ENXIO;
 #endif
+	}
 
-    }
+	if (pci_irq_line)
+		dev->irq = pci_irq_line;
 
-    if (pci_irq_line)
-	dev->irq = pci_irq_line;
+	if (dev->irq < 2) 
+	{
+		autoirq_setup(0);
+		outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
+		outb_p(0x00, ioaddr + EN0_RCNTLO);
+		outb_p(0x00, ioaddr + EN0_RCNTHI);
+		outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
+		mdelay(10);		/* wait 10ms for interrupt to propagate */
+		outb_p(0x00, ioaddr + EN0_IMR); 		/* Mask it again. */
+		dev->irq = autoirq_report(0);
+		if (ei_debug > 2)
+			printk(" autoirq is %d\n", dev->irq);
+	} else if (dev->irq == 2)
+		/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
+		   or don't know which one to set. */
+		dev->irq = 9;
+
+	if (! dev->irq) {
+		printk(" failed to detect IRQ line.\n");
+		return EAGAIN;
+	}
 
-    if (dev->irq < 2) {
-	autoirq_setup(0);
-	outb_p(0x50, ioaddr + EN0_IMR);	/* Enable one interrupt. */
-	outb_p(0x00, ioaddr + EN0_RCNTLO);
-	outb_p(0x00, ioaddr + EN0_RCNTHI);
-	outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */
-	mdelay(10);		/* wait 10ms for interrupt to propagate */
-	outb_p(0x00, ioaddr + EN0_IMR); 		/* Mask it again. */
-	dev->irq = autoirq_report(0);
-	if (ei_debug > 2)
-	    printk(" autoirq is %d\n", dev->irq);
-    } else if (dev->irq == 2)
-	/* Fixup for users that don't know that IRQ 2 is really IRQ 9,
-	   or don't know which one to set. */
-	dev->irq = 9;
-
-    if (! dev->irq) {
-	printk(" failed to detect IRQ line.\n");
-	return EAGAIN;
-    }
-
-    /* Allocate dev->priv and fill in 8390 specific dev fields. */
-    if (ethdev_init(dev)) {
-        printk (" unable to get memory for dev->priv.\n");
-        return -ENOMEM;
-    }
+	/* Allocate dev->priv and fill in 8390 specific dev fields. */
+	if (ethdev_init(dev)) 
+	{
+        	printk (" unable to get memory for dev->priv.\n");
+        	return -ENOMEM;
+	}
    
-    /* Snarf the interrupt now.  There's no point in waiting since we cannot
-       share and the board will usually be enabled. */
-    {
-	int irqval = request_irq(dev->irq, ei_interrupt,
+	/* Snarf the interrupt now.  There's no point in waiting since we cannot
+	   share and the board will usually be enabled. */
+
+	{
+		int irqval = request_irq(dev->irq, ei_interrupt,
 				 pci_irq_line ? SA_SHIRQ : 0, name, dev);
-	if (irqval) {
-	    printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
+		if (irqval) {
+			printk (" unable to get IRQ %d (irqval=%d).\n", dev->irq, irqval);
+			kfree(dev->priv);
+			dev->priv = NULL;
+			return EAGAIN;
+		}
+	}
+	dev->base_addr = ioaddr;
+	request_region(ioaddr, NE_IO_EXTENT, name);
+
+	for(i = 0; i < ETHER_ADDR_LEN; i++) {
+		printk(" %2.2x", SA_prom[i]);
+		dev->dev_addr[i] = SA_prom[i];
+	}
+
+	printk("\n%s: %s found at %#x, using IRQ %d.\n",
+		dev->name, name, ioaddr, dev->irq);
 
-            kfree(dev->priv);
-	    dev->priv = NULL;
-	    return EAGAIN;
-	}
-    }
-    dev->base_addr = ioaddr;
-    request_region(ioaddr, NE_IO_EXTENT, name);
-
-    for(i = 0; i < ETHER_ADDR_LEN; i++) {
-	printk(" %2.2x", SA_prom[i]);
-	dev->dev_addr[i] = SA_prom[i];
-    }
-
-    printk("\n%s: %s found at %#x, using IRQ %d.\n",
-	   dev->name, name, ioaddr, dev->irq);
-
-    ei_status.name = name;
-    ei_status.tx_start_page = start_page;
-    ei_status.stop_page = stop_page;
-    ei_status.word16 = (wordlength == 2);
+	ei_status.name = name;
+	ei_status.tx_start_page = start_page;
+	ei_status.stop_page = stop_page;
+	ei_status.word16 = (wordlength == 2);
 
-    ei_status.rx_start_page = start_page + TX_PAGES;
+	ei_status.rx_start_page = start_page + TX_PAGES;
 #ifdef PACKETBUF_MEMSIZE
-    /* Allow the packet buffer size to be overridden by know-it-alls. */
-    ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+	 /* Allow the packet buffer size to be overridden by know-it-alls. */
+	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
 #endif
 
-    ei_status.reset_8390 = &ne_reset_8390;
-    ei_status.block_input = &ne_block_input;
-    ei_status.block_output = &ne_block_output;
-    ei_status.get_8390_hdr = &ne_get_8390_hdr;
-    dev->open = &ne_open;
-    dev->stop = &ne_close;
-    NS8390_init(dev, 0);
-    return 0;
+	ei_status.reset_8390 = &ne_reset_8390;
+	ei_status.block_input = &ne_block_input;
+	ei_status.block_output = &ne_block_output;
+	ei_status.get_8390_hdr = &ne_get_8390_hdr;
+	dev->open = &ne_open;
+	dev->stop = &ne_close;
+	NS8390_init(dev, 0);
+	return 0;
 }
 
-static int
-ne_open(struct device *dev)
+static int ne_open(struct device *dev)
 {
-    ei_open(dev);
-    MOD_INC_USE_COUNT;
-    return 0;
+	ei_open(dev);
+	MOD_INC_USE_COUNT;
+	return 0;
 }
 
-static int
-ne_close(struct device *dev)
+static int ne_close(struct device *dev)
 {
-    if (ei_debug > 1)
-	printk("%s: Shutting down ethercard.\n", dev->name);
-    ei_close(dev);
-    MOD_DEC_USE_COUNT;
-    return 0;
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name);
+	ei_close(dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 /* Hard reset the card.  This used to pause for the same period that a
    8390 reset command required, but that shouldn't be necessary. */
-static void
-ne_reset_8390(struct device *dev)
+
+static void ne_reset_8390(struct device *dev)
 {
-    unsigned long reset_start_time = jiffies;
+	unsigned long reset_start_time = jiffies;
 
-    if (ei_debug > 1) printk("resetting the 8390 t=%ld...", jiffies);
+	if (ei_debug > 1)
+		printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies);
 
-    /* DON'T change these to inb_p/outb_p or reset will fail on clones. */
-    outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
+	/* DON'T change these to inb_p/outb_p or reset will fail on clones. */
+	outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET);
 
-    ei_status.txing = 0;
-    ei_status.dmaing = 0;
+	ei_status.txing = 0;
+	ei_status.dmaing = 0;
 
-    /* This check _should_not_ be necessary, omit eventually. */
-    while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
-	if (jiffies - reset_start_time > 2*HZ/100) {
-	    printk("%s: ne_reset_8390() did not complete.\n", dev->name);
-	    break;
-	}
-    outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
+	/* This check _should_not_ be necessary, omit eventually. */
+	while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0)
+		if (jiffies - reset_start_time > 2*HZ/100) {
+			printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name);
+			break;
+		}
+	outb_p(ENISR_RESET, NE_BASE + EN0_ISR);	/* Ack intr. */
 }
 
 /* Grab the 8390 specific header. Similar to the block_input routine, but
    we don't need to be concerned with ring wrap as the header will be at
    the start of a page, so we optimize accordingly. */
 
-static void
-ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
+static void ne_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
 {
+	int nic_base = dev->base_addr;
 
-    int nic_base = dev->base_addr;
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
 
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk("%s: DMAing conflict in ne_get_8390_hdr "
-	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock,
-	   dev->interrupt);
-	return;
-    }
+	if (ei_status.dmaing) 
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr "
+			"[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock,
+			dev->interrupt);
+		return;
+	}
 
-    ei_status.dmaing |= 0x01;
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
-    outb_p(0, nic_base + EN0_RCNTHI);
-    outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
-    outb_p(ring_page, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-
-    if (ei_status.word16)
-	insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
-    else
-	insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
+	outb_p(0, nic_base + EN0_RCNTHI);
+	outb_p(0, nic_base + EN0_RSARLO);		/* On page boundary */
+	outb_p(ring_page, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+
+	if (ei_status.word16)
+		insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	else
+		insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
 
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
 }
 
 /* Block input and output, similar to the Crynwr packet driver.  If you
@@ -558,164 +578,176 @@
    The NEx000 doesn't share the on-board packet memory -- you have to put
    the packet out through the "remote DMA" dataport using outb. */
 
-static void
-ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
+static void ne_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
 {
 #ifdef NE_SANITY_CHECK
-    int xfer_count = count;
+	int xfer_count = count;
 #endif
-    int nic_base = dev->base_addr;
-    char *buf = skb->data;
+	int nic_base = dev->base_addr;
+	char *buf = skb->data;
 
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk("%s: DMAing conflict in ne_block_input "
-	   "[DMAstat:%d][irqlock:%d][intr:%ld].\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock,
-	   dev->interrupt);
-	return;
-    }
-    ei_status.dmaing |= 0x01;
-    outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
-    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-    outb_p(count >> 8, nic_base + EN0_RCNTHI);
-    outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
-    outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-    if (ei_status.word16) {
-      insw(NE_BASE + NE_DATAPORT,buf,count>>1);
-      if (count & 0x01) {
-	buf[count-1] = inb(NE_BASE + NE_DATAPORT);
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) 
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_input "
+			"[DMAstat:%d][irqlock:%d][intr:%ld].\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock,
+			dev->interrupt);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8, nic_base + EN0_RCNTHI);
+	outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO);
+	outb_p(ring_offset >> 8, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) 
+	{
+		insw(NE_BASE + NE_DATAPORT,buf,count>>1);
+		if (count & 0x01) 
+		{
+			buf[count-1] = inb(NE_BASE + NE_DATAPORT);
 #ifdef NE_SANITY_CHECK
-	xfer_count++;
+			xfer_count++;
 #endif
-      }
-    } else {
-	insb(NE_BASE + NE_DATAPORT, buf, count);
-    }
+		}
+	} else {
+		insb(NE_BASE + NE_DATAPORT, buf, count);
+	}
 
 #ifdef NE_SANITY_CHECK
-    /* This was for the ALPHA version only, but enough people have
-       been encountering problems so it is still here.  If you see
-       this message you either 1) have a slightly incompatible clone
-       or 2) have noise/speed problems with your bus. */
-    if (ei_debug > 1) {		/* DMA termination address check... */
-	int addr, tries = 20;
-	do {
-	    /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
-	       -- it's broken for Rx on some cards! */
-	    int high = inb_p(nic_base + EN0_RSARHI);
-	    int low = inb_p(nic_base + EN0_RSARLO);
-	    addr = (high << 8) + low;
-	    if (((ring_offset + xfer_count) & 0xff) == low)
-		break;
-	} while (--tries > 0);
-	if (tries <= 0)
-	    printk("%s: RX transfer address mismatch,"
-		   "%#4.4x (expected) vs. %#4.4x (actual).\n",
-		   dev->name, ring_offset + xfer_count, addr);
-    }
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here.  If you see
+	   this message you either 1) have a slightly incompatible clone
+	   or 2) have noise/speed problems with your bus. */
+
+	if (ei_debug > 1) 
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			/* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here
+			   -- it's broken for Rx on some cards! */
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if (((ring_offset + xfer_count) & 0xff) == low)
+				break;
+		} while (--tries > 0);
+	 	if (tries <= 0)
+			printk(KERN_WARNING "%s: RX transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, ring_offset + xfer_count, addr);
+	}
 #endif
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
 }
 
-static void
-ne_block_output(struct device *dev, int count,
+static void ne_block_output(struct device *dev, int count,
 		const unsigned char *buf, const int start_page)
 {
-    int nic_base = NE_BASE;
-    unsigned long dma_start;
+	int nic_base = NE_BASE;
+	unsigned long dma_start;
 #ifdef NE_SANITY_CHECK
-    int retries = 0;
+	int retries = 0;
 #endif
 
-    /* Round the count up for word writes.  Do we need to do this?
-       What effect will an odd byte count have on the 8390?
-       I should check someday. */
-    if (ei_status.word16 && (count & 0x01))
-      count++;
-
-    /* This *shouldn't* happen. If it does, it's the last thing you'll see */
-    if (ei_status.dmaing) {
-	printk("%s: DMAing conflict in ne_block_output."
-	   "[DMAstat:%d][irqlock:%d][intr:%ld]\n",
-	   dev->name, ei_status.dmaing, ei_status.irqlock,
-	   dev->interrupt);
-	return;
-    }
-    ei_status.dmaing |= 0x01;
-    /* We should already be in page 0, but to be safe... */
-    outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
+	/* Round the count up for word writes.  Do we need to do this?
+	   What effect will an odd byte count have on the 8390?
+	   I should check someday. */
+	   
+	if (ei_status.word16 && (count & 0x01))
+		count++;
+
+	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
+	if (ei_status.dmaing) 
+	{
+		printk(KERN_EMERG "%s: DMAing conflict in ne_block_output."
+			"[DMAstat:%d][irqlock:%d][intr:%ld]\n",
+			dev->name, ei_status.dmaing, ei_status.irqlock,
+			dev->interrupt);
+		return;
+	}
+	ei_status.dmaing |= 0x01;
+	/* We should already be in page 0, but to be safe... */
+	outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
 
 #ifdef NE_SANITY_CHECK
- retry:
+retry:
 #endif
 
 #ifdef NE8390_RW_BUGFIX
-    /* Handle the read-before-write bug the same way as the
-       Crynwr packet driver -- the NatSemi method doesn't work.
-       Actually this doesn't always work either, but if you have
-       problems with your NEx000 this is better than nothing! */
-    outb_p(0x42, nic_base + EN0_RCNTLO);
-    outb_p(0x00,   nic_base + EN0_RCNTHI);
-    outb_p(0x42, nic_base + EN0_RSARLO);
-    outb_p(0x00, nic_base + EN0_RSARHI);
-    outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
-    /* Make certain that the dummy read has occurred. */
-    udelay(6);
-#endif
-
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);
-
-   /* Now the normal output. */
-    outb_p(count & 0xff, nic_base + EN0_RCNTLO);
-    outb_p(count >> 8,   nic_base + EN0_RCNTHI);
-    outb_p(0x00, nic_base + EN0_RSARLO);
-    outb_p(start_page, nic_base + EN0_RSARHI);
-
-    outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-    if (ei_status.word16) {
-	outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
-    } else {
-	outsb(NE_BASE + NE_DATAPORT, buf, count);
-    }
+	/* Handle the read-before-write bug the same way as the
+	   Crynwr packet driver -- the NatSemi method doesn't work.
+	   Actually this doesn't always work either, but if you have
+	   problems with your NEx000 this is better than nothing! */
+	   
+	outb_p(0x42, nic_base + EN0_RCNTLO);
+	outb_p(0x00,   nic_base + EN0_RCNTHI);
+	outb_p(0x42, nic_base + EN0_RSARLO);
+	outb_p(0x00, nic_base + EN0_RSARHI);
+	outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD);
+	/* Make certain that the dummy read has occurred. */
+	udelay(6);
+#endif
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);
+
+	/* Now the normal output. */
+	outb_p(count & 0xff, nic_base + EN0_RCNTLO);
+	outb_p(count >> 8,   nic_base + EN0_RCNTHI);
+	outb_p(0x00, nic_base + EN0_RSARLO);
+	outb_p(start_page, nic_base + EN0_RSARHI);
+
+	outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
+	if (ei_status.word16) {
+		outsw(NE_BASE + NE_DATAPORT, buf, count>>1);
+	} else {
+		outsb(NE_BASE + NE_DATAPORT, buf, count);
+	}
 
-    dma_start = jiffies;
+	dma_start = jiffies;
 
 #ifdef NE_SANITY_CHECK
-    /* This was for the ALPHA version only, but enough people have
-       been encountering problems so it is still here. */
-    if (ei_debug > 1) {		/* DMA termination address check... */
-	int addr, tries = 20;
-	do {
-	    int high = inb_p(nic_base + EN0_RSARHI);
-	    int low = inb_p(nic_base + EN0_RSARLO);
-	    addr = (high << 8) + low;
-	    if ((start_page << 8) + count == addr)
-		break;
-	} while (--tries > 0);
-	if (tries <= 0) {
-	    printk("%s: Tx packet transfer address mismatch,"
-		   "%#4.4x (expected) vs. %#4.4x (actual).\n",
-		   dev->name, (start_page << 8) + count, addr);
-	    if (retries++ == 0)
-		goto retry;
-	}
-    }
-#endif
-
-    while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
-	if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
-		printk("%s: timeout waiting for Tx RDC.\n", dev->name);
-		ne_reset_8390(dev);
-		NS8390_init(dev,1);
-		break;
-	}
-
-    outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-    ei_status.dmaing &= ~0x01;
-    return;
+	/* This was for the ALPHA version only, but enough people have
+	   been encountering problems so it is still here. */
+	
+	if (ei_debug > 1) 
+	{
+		/* DMA termination address check... */
+		int addr, tries = 20;
+		do {
+			int high = inb_p(nic_base + EN0_RSARHI);
+			int low = inb_p(nic_base + EN0_RSARLO);
+			addr = (high << 8) + low;
+			if ((start_page << 8) + count == addr)
+				break;
+		} while (--tries > 0);
+
+		if (tries <= 0) 
+		{
+			printk(KERN_WARNING "%s: Tx packet transfer address mismatch,"
+				"%#4.4x (expected) vs. %#4.4x (actual).\n",
+				dev->name, (start_page << 8) + count, addr);
+			if (retries++ == 0)
+				goto retry;
+		}
+	}
+#endif
+
+	while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0)
+		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
+			printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name);
+			ne_reset_8390(dev);
+			NS8390_init(dev,1);
+			break;
+		}
+
+	outb_p(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
+	ei_status.dmaing &= ~0x01;
+	return;
 }
 
 
@@ -740,13 +772,16 @@
 MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
 MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i");
 
+#ifdef CONFIG_PCI
+MODULE_PARM(probe_pci, "i");
+#endif
+
 /* This is set up so that no ISA autoprobe takes place. We can't guarantee
 that the ne2k probe is the last 8390 based probe to take place (as it
 is at boot) and so the probe will get confused by any other 8390 cards.
 ISA device autoprobes on a running machine are not recommended anyway. */
 
-int
-init_module(void)
+int init_module(void)
 {
 	int this_dev, found = 0;
 
@@ -775,8 +810,7 @@
 	return 0;
 }
 
-void
-cleanup_module(void)
+void cleanup_module(void)
 {
 	int this_dev;
 
@@ -786,7 +820,6 @@
 			void *priv = dev->priv;
 			free_irq(dev->irq, dev);
 			release_region(dev->base_addr, NE_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ne2.c linux/drivers/net/ne2.c
--- v2.1.131/linux/drivers/net/ne2.c	Sun Nov  8 14:03:00 1998
+++ linux/drivers/net/ne2.c	Wed Dec 16 13:35:49 1998
@@ -677,10 +677,7 @@
 			mca_mark_as_unused(ei_status.priv);
 			mca_set_adapter_procfn( ei_status.priv, NULL, NULL);
 			kfree(dev->priv);
-			dev->priv = NULL;
 			free_irq(dev->irq, dev);
-			/* removed (temporary) fot */
-			/* irq2dev_map[dev->irq] = NULL; */
 			release_region(dev->base_addr, NE_IO_EXTENT);
 			unregister_netdev(dev);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c
--- v2.1.131/linux/drivers/net/ne3210.c	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/ne3210.c	Wed Dec 16 13:35:49 1998
@@ -421,7 +421,6 @@
 			release_region(dev->base_addr, NE3210_IO_EXTENT);
 			if (ei_status.reg0)
 				iounmap((void *)dev->mem_start);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.1.131/linux/drivers/net/net_init.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/net/net_init.c	Fri Dec 18 09:40:15 1998
@@ -165,6 +165,9 @@
 #endif
 
 #ifdef CONFIG_HIPPI
+#define MAX_HIP_CARDS	4
+static struct device *hipdev_index[MAX_HIP_CARDS];
+
 static int hippi_change_mtu(struct device *dev, int new_mtu)
 {
 	/*
@@ -193,32 +196,60 @@
 
 struct device *init_hippi_dev(struct device *dev, int sizeof_priv)
 {
-	struct device *tmp_dev;		/* pointer to a device structure */
-
-	/* Find next free HIPPI entry */
+	int new_device = 0;
+	int i;
 
-	for (tmp_dev = dev; tmp_dev != NULL; tmp_dev = tmp_dev->next)
-		if ((strncmp(tmp_dev->name, "hip", 3) == 0) &&
-		    (tmp_dev->base_addr == 0))
-			break;
-
-	if (tmp_dev == NULL)
-	{
-		printk("Could not find free HIPPI device structure.\n");
-		return NULL;
+	/* Use an existing correctly named device in Space.c:dev_base. */
+	if (dev == NULL) {
+		int alloc_size = sizeof(struct device) + sizeof("hip%d  ")
+			+ sizeof_priv + 3;
+		struct device *cur_dev;
+		char pname[8];
+
+		for (i = 0; i < MAX_HIP_CARDS; ++i)
+			if (hipdev_index[i] == NULL) {
+				sprintf(pname, "hip%d", i);
+				for (cur_dev = dev_base; cur_dev; cur_dev = cur_dev->next)
+					if (strcmp(pname, cur_dev->name) == 0) {
+						dev = cur_dev;
+						dev->init = NULL;
+						sizeof_priv = (sizeof_priv + 3) & ~3;
+						dev->priv = sizeof_priv
+							  ? kmalloc(sizeof_priv, GFP_KERNEL)
+							  :	NULL;
+						if (dev->priv) memset(dev->priv, 0, sizeof_priv);
+						goto hipfound;
+					}
+			}
+
+		alloc_size &= ~3;		/* Round to dword boundary. */
+
+		dev = (struct device *)kmalloc(alloc_size, GFP_KERNEL);
+		memset(dev, 0, alloc_size);
+		if (sizeof_priv)
+			dev->priv = (void *) (dev + 1);
+		dev->name = sizeof_priv + (char *)(dev + 1);
+		new_device = 1;
 	}
-		
-	tmp_dev->init = NULL;
-	sizeof_priv = (sizeof_priv + 3) & ~3;
-	tmp_dev->priv = sizeof_priv ?								kmalloc(sizeof_priv, GFP_KERNEL) : NULL;
 
-	if (tmp_dev->priv)
-		memset(dev->priv, 0, sizeof_priv);
+hipfound:				/* From the double loop above. */
 
-	/* Initialize remaining device structure information */
+	if (dev->name &&
+		((dev->name[0] == '\0') || (dev->name[0] == ' '))) {
+		for (i = 0; i < MAX_HIP_CARDS; ++i)
+			if (hipdev_index[i] == NULL) {
+				sprintf(dev->name, "hip%d", i);
+				hipdev_index[i] = dev;
+				break;
+			}
+	}
 
-	hippi_setup(tmp_dev);
-	return tmp_dev;
+	hippi_setup(dev);
+	
+	if (new_device)
+		register_netdevice(dev);
+
+	return dev;
 }
 
 static int hippi_neigh_setup_dev(struct device *dev, struct neigh_parms *p)
@@ -312,6 +343,19 @@
 #ifdef CONFIG_HIPPI
 void hippi_setup(struct device *dev)
 {
+	int i;
+
+	if (dev->name && (strncmp(dev->name, "hip", 3) == 0)) {
+		i = simple_strtoul(dev->name + 3, NULL, 0);
+		if (hipdev_index[i] == NULL) {
+			hipdev_index[i] = dev;
+		}
+		else if (dev != hipdev_index[i]) {
+			printk("hippi_setup: Ouch! Someone else took %s\n",
+				dev->name);
+		}
+	}
+
 	dev->set_multicast_list	= NULL;
 	dev->change_mtu			= hippi_change_mtu;
 	dev->hard_header		= hippi_header;
diff -u --recursive --new-file v2.1.131/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
--- v2.1.131/linux/drivers/net/ppp.c	Sun Nov  8 14:03:00 1998
+++ linux/drivers/net/ppp.c	Fri Dec 18 09:40:15 1998
@@ -2041,7 +2041,7 @@
 		return 0;
 	new_count = slhc_uncompress(ppp->slcomp, skb->data + PPP_HDRLEN,
 				    skb->len - PPP_HDRLEN);
-	if (new_count < 0) {
+	if (new_count<=0) {
 		if (ppp->flags & SC_DEBUG)
 			printk(KERN_NOTICE
 			       "ppp: error in VJ decompression\n");
diff -u --recursive --new-file v2.1.131/linux/drivers/net/rcif.h linux/drivers/net/rcif.h
--- v2.1.131/linux/drivers/net/rcif.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rcif.h	Fri Dec 18 09:39:34 1998
@@ -0,0 +1,235 @@
+/*
+** *************************************************************************
+**
+**
+**     R C I F . H
+**
+**
+**  RedCreek InterFace include file.
+**
+**  ---------------------------------------------------------------------
+**  ---     Copyright (c) 1998, RedCreek Communications Inc.          ---
+**  ---                   All rights reserved.                        ---
+**  ---------------------------------------------------------------------
+**
+** File Description:
+**
+** Header file private ioctl commands.
+**
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation; either version 2 of the License, or
+**  (at your option) any later version.
+
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+** *************************************************************************
+*/
+
+#ifndef RCIF_H
+#define RCIF_H
+
+/* The following protocol revision # should be incremented every time
+   a new protocol or new structures are used in this file. */
+int USER_PROTOCOL_REV = 1;     /* used to track different protocol revisions */
+
+/* define a single TCB & buffer */
+typedef struct                  /* a single buffer */
+{
+     U32 context;               /* context */
+     U32 scount;                /* segment count */
+     U32 size;                  /* segment size */
+     U32 addr;                  /* segment physical address */
+}
+__attribute__((packed))
+singleB, *psingleB ;
+typedef struct                  /* a single TCB */
+{
+     /*
+     **  +-----------------------+
+     **  |         1             |  one buffer in the TCB
+     **  +-----------------------+
+     **  |  <user's Context>     |  user's buffer reference
+     **  +-----------------------+
+     **  |         1             |  one segment buffer
+     **  +-----------------------+                            _
+     **  |    <buffer size>      |  size                       \ 
+     **  +-----------------------+                              \ segment descriptor
+     **  |  <physical address>   |  physical address of buffer  /
+     **  +-----------------------+                            _/
+     */
+     U32 bcount;                /* buffer count */
+     singleB b;                 /* buffer */
+
+}
+__attribute__((packed))
+singleTCB, *psingleTCB;
+
+/*
+   When adding new entries, please add all 5 related changes, since 
+   it helps keep everything consistent:
+      1) User structure entry
+      2) User data entry
+      3) Structure short-cut entry
+      4) Data short-cut entry
+      5) Command identifier entry
+
+   For Example ("GETSPEED"):
+      1) struct  RCgetspeed_tag { U32 LinkSpeedCode; } RCgetspeed;
+      2) struct  RCgetspeed_tag *getspeed;
+      3) #define RCUS_GETSPEED  data.RCgetspeed;
+      4) #define RCUD_GETSPEED  _RC_user_data.getspeed
+      5) #define RCUC_GETSPEED  0x02
+  
+   Notes for the "GETSPEED" entry, above:
+      1) RCgetspeed      - RC{name}
+         RCgetspeed_tag  - RC{name}_tag
+         LinkSpeedCode   - create any structure format desired (not too large,
+                           since memory will be unioned with all other entries)
+      2) RCgetspeed_tag  - RC{name}_tag chosen in #1
+         getspeed        - arbitrary name (ptr to structure in #1)
+      3) RCUS_GETSPEED   - RCUS_{NAME}   ("NAME" & "name" do not have to the same)
+         data.RCgetspeed - data.RC{name}  ("RC{name}" from #1)
+      4) RCUD_GETSPEED   - _RC_user_data.getspeed  ("getspeed" from #2)
+      5) RCUC_GETSPEED   - unique hex identifier entry.
+*/
+
+typedef struct RC_user_tag RCuser_struct;
+
+/* 1) User structure entry */
+struct RC_user_tag
+{
+    int cmd;
+    union
+    {
+        /* GETINFO structure */
+        struct RCgetinfo_tag {
+            unsigned long int mem_start;
+            unsigned long int mem_end;
+            unsigned long int base_addr;
+            unsigned char irq;
+            unsigned char dma;
+            unsigned char port;
+        } RCgetinfo;                    /* <---- RCgetinfo */
+     
+        /* GETSPEED structure */
+        struct  RCgetspeed_tag {
+            U32 LinkSpeedCode;
+        } RCgetspeed;                   /* <---- RCgetspeed */
+  
+        /* GETFIRMWAREVER structure */
+        #define FirmStringLen 80
+        struct RCgetfwver_tag {
+            U8 FirmString[FirmStringLen];
+        } RCgetfwver;                   /* <---- RCgetfwver */
+  
+        /* GETIPANDMASK structure */
+        struct RCgetipnmask_tag {
+            U32 IpAddr;
+            U32 NetMask;
+        } RCgetipandmask;               /* <---- RCgetipandmask */
+
+        /* GETMAC structure */
+        #define MAC_SIZE 10
+        struct RCgetmac_tag {
+            U8 mac[MAC_SIZE];
+        } RCgetmac;                     /* <---- RCgetmac */
+
+        /* GETLINKSTATUS structure */
+        struct RCgetlnkstatus_tag {
+            U32 ReturnStatus;
+        } RCgetlnkstatus;               /* <---- RCgetlnkstatus */
+
+        /* GETLINKSTATISTICS structure */
+        struct RCgetlinkstats_tag {
+            RCLINKSTATS StatsReturn;
+        } RCgetlinkstats;               /* <---- RCgetlinkstats */
+
+        /* DEFAULT structure (when no command was recognized) */
+        struct RCdefault_tag {
+            int rc;
+        } RCdefault;                    /* <---- RCdefault */
+
+    } data;
+
+};   /* struct RC_user_tag { ... } */
+
+/* 2) User data entry */
+/* RCUD = RedCreek User Data */
+union RC_user_data_tag {        /* structure tags used are taken from RC_user_tag structure above */
+    struct RCgetinfo_tag      *getinfo;
+    struct RCgetspeed_tag     *getspeed;
+    struct RCgetfwver_tag     *getfwver;
+    struct RCgetipnmask_tag   *getipandmask;
+    struct RCgetmac_tag       *getmac;
+    struct RCgetlnkstatus_tag *getlinkstatus;
+    struct RCgetlinkstats_tag *getlinkstatistics;
+    struct RCdefault_tag      *rcdefault;
+} _RC_user_data;  /* declare as a global, so the defines below will work */
+
+/* 3) Structure short-cut entry */
+/* define structure short-cuts */   /* structure names are taken from RC_user_tag structure above */
+#define RCUS_GETINFO           data.RCgetinfo;
+#define RCUS_GETSPEED          data.RCgetspeed;
+#define RCUS_GETFWVER          data.RCgetfwver;
+#define RCUS_GETIPANDMASK      data.RCgetipandmask;
+#define RCUS_GETMAC            data.RCgetmac;
+#define RCUS_GETLINKSTATUS     data.RCgetlnkstatus;
+#define RCUS_GETLINKSTATISTICS data.RCgetlinkstats;
+#define RCUS_DEFAULT           data.RCdefault;
+
+/* 4) Data short-cut entry */
+/* define data short-cuts */    /* pointer names are from RC_user_data_tag union (just below RC_user_tag) */
+#define RCUD_GETINFO           _RC_user_data.getinfo
+#define RCUD_GETSPEED          _RC_user_data.getspeed
+#define RCUD_GETFWVER          _RC_user_data.getfwver
+#define RCUD_GETIPANDMASK      _RC_user_data.getipandmask
+#define RCUD_GETMAC            _RC_user_data.getmac
+#define RCUD_GETLINKSTATUS     _RC_user_data.getlinkstatus
+#define RCUD_GETLINKSTATISTICS _RC_user_data.getlinkstatistics
+#define RCUD_DEFAULT           _RC_user_data.rcdefault
+
+/* 5) Command identifier entry */
+/* define command identifiers */
+#define RCUC_GETINFO            0x01
+#define RCUC_GETSPEED           0x02
+#define RCUC_GETFWVER           0x03
+#define RCUC_GETIPANDMASK       0x04
+#define RCUC_GETMAC             0x05
+#define RCUC_GETLINKSTATUS      0x06
+#define RCUC_GETLINKSTATISTICS  0x07
+#define RCUC_DEFAULT            0xff
+
+/* define ioctl commands to use, when talking to RC 45/PCI driver */
+#define RCU_PROTOCOL_REV         SIOCDEVPRIVATE
+#define RCU_COMMAND              SIOCDEVPRIVATE+1
+
+/*
+   Intended use for the above defines is shown below (GETINFO, as this example):
+
+      RCuser_struct RCuser;           // declare RCuser structure
+      struct ifreq ifr;               // declare an interface request structure
+
+      RCuser.cmd = RCUC_GETINFO;           // set user command to GETINFO
+      ifr->ifr_data = (caddr_t) &RCuser;   // set point to user structure
+
+      sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);   // get a socket
+      ioctl(sock, RCU_COMMAND, &ifr);                  // do ioctl on socket
+
+      RCUD_GETINFO = &RCuser.RCUS_GETINFO;   // set data pointer for GETINFO
+
+      // print results
+      printf("memory 0x%lx-0x%lx, base address 0x%x, irq 0x%x\n",
+              RCUD_GETINFO->mem_start, RCUD_GETINFO->mem_end,
+              RCUD_GETINFO->base_addr, RCUD_GETINFO->irq);
+*/
+
+#endif   /* RCIF_H */
+
diff -u --recursive --new-file v2.1.131/linux/drivers/net/rcmtl.c linux/drivers/net/rcmtl.c
--- v2.1.131/linux/drivers/net/rcmtl.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rcmtl.c	Fri Dec 18 09:39:34 1998
@@ -0,0 +1,2058 @@
+/*
+** *************************************************************************
+**
+**
+**     R C M T L . C             $Revision: 1.1 $
+**
+**
+**  RedCreek Message Transport Layer program module.
+**
+**  ---------------------------------------------------------------------
+**  ---     Copyright (c) 1997-1998, RedCreek Communications Inc.     ---
+**  ---                   All rights reserved.                        ---
+**  ---------------------------------------------------------------------
+**
+** File Description:
+**
+** Host side message transport layer.
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation; either version 2 of the License, or
+**  (at your option) any later version.
+
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+***************************************************************************/
+
+#undef DEBUG
+
+#define RC_LINUX_MODULE
+#include "rcmtl.h"
+
+#define dprintf kprintf
+
+extern int printk(const char * fmt, ...);
+
+ /* RedCreek LAN device Target ID */
+#define LAN_TARGET_ID  0x10 
+ /* RedCreek's OSM default LAN receive Initiator */
+#define DEFAULT_RECV_INIT_CONTEXT  0xA17  
+
+
+/*
+** message structures
+*/
+
+#define    TID_SZ                                  12
+#define    FUNCTION_SZ                             8
+
+/* Transaction Reply Lists (TRL) Control Word structure */
+
+#define    TRL_SINGLE_FIXED_LENGTH           0x00
+#define    TRL_SINGLE_VARIABLE_LENGTH        0x40
+#define    TRL_MULTIPLE_FIXED_LENGTH         0x80
+
+/* LAN Class specific functions */
+
+#define    LAN_PACKET_SEND                         0x3B
+#define    LAN_SDU_SEND                            0x3D
+#define    LAN_RECEIVE_POST                        0x3E
+#define    LAN_RESET                               0x35
+#define    LAN_SHUTDOWN                            0x37
+
+/* Private Class specfic function */
+#define    RC_PRIVATE                                 0xFF
+
+/*  RC Executive Function Codes.  */
+
+#define    RC_CMD_ADAPTER_ASSIGN                     0xB3
+#define    RC_CMD_ADAPTER_READ                       0xB2
+#define    RC_CMD_ADAPTER_RELEASE                    0xB5
+#define    RC_CMD_BIOS_INFO_SET                      0xA5
+#define    RC_CMD_BOOT_DEVICE_SET                    0xA7
+#define    RC_CMD_CONFIG_VALIDATE                    0xBB
+#define    RC_CMD_CONN_SETUP                         0xCA
+#define    RC_CMD_DEVICE_ASSIGN                      0xB7
+#define    RC_CMD_DEVICE_RELEASE                     0xB9
+#define    RC_CMD_HRT_GET                            0xA8
+#define    RC_CMD_ADAPTER_CLEAR                          0xBE
+#define    RC_CMD_ADAPTER_CONNECT                        0xC9
+#define    RC_CMD_ADAPTER_RESET                          0xBD
+#define    RC_CMD_LCT_NOTIFY                         0xA2
+#define    RC_CMD_OUTBOUND_INIT                      0xA1
+#define    RC_CMD_PATH_ENABLE                        0xD3
+#define    RC_CMD_PATH_QUIESCE                       0xC5
+#define    RC_CMD_PATH_RESET                         0xD7
+#define    RC_CMD_STATIC_MF_CREATE                   0xDD
+#define    RC_CMD_STATIC_MF_RELEASE                  0xDF
+#define    RC_CMD_STATUS_GET                         0xA0
+#define    RC_CMD_SW_DOWNLOAD                        0xA9
+#define    RC_CMD_SW_UPLOAD                          0xAB
+#define    RC_CMD_SW_REMOVE                          0xAD
+#define    RC_CMD_SYS_ENABLE                         0xD1
+#define    RC_CMD_SYS_MODIFY                         0xC1
+#define    RC_CMD_SYS_QUIESCE                        0xC3
+#define    RC_CMD_SYS_TAB_SET                        0xA3
+
+
+ /* Init Outbound Q status */
+#define    RC_CMD_OUTBOUND_INIT_IN_PROGRESS          0x01
+#define    RC_CMD_OUTBOUND_INIT_REJECTED             0x02
+#define    RC_CMD_OUTBOUND_INIT_FAILED               0x03
+#define    RC_CMD_OUTBOUND_INIT_COMPLETE             0x04
+
+
+#define    UTIL_NOP                                0x00
+
+
+/* RC Get Status State values */
+
+#define    ADAPTER_STATE_INITIALIZING                  0x01
+#define    ADAPTER_STATE_RESET                         0x02
+#define    ADAPTER_STATE_HOLD                          0x04
+#define    ADAPTER_STATE_READY                         0x05
+#define    ADAPTER_STATE_OPERATIONAL                   0x08
+#define    ADAPTER_STATE_FAILED                        0x10
+#define    ADAPTER_STATE_FAULTED                       0x11
+
+
+/* Defines for Request Status Codes:  Table 3-1 Reply Status Codes.  */
+
+#define    RC_REPLY_STATUS_SUCCESS                    0x00
+#define    RC_REPLY_STATUS_ABORT_DIRTY                0x01
+#define    RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER     0x02
+#define    RC_REPLY_STATUS_ABORT_PARTIAL_TRANSFER     0x03
+#define    RC_REPLY_STATUS_ERROR_DIRTY                0x04
+#define    RC_REPLY_STATUS_ERROR_NO_DATA_TRANSFER     0x05
+#define    RC_REPLY_STATUS_ERROR_PARTIAL_TRANSFER     0x06
+#define    RC_REPLY_STATUS_PROCESS_ABORT_DIRTY        0x07
+#define    RC_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER   0x08
+#define    RC_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER   0x09
+#define    RC_REPLY_STATUS_TRANSACTION_ERROR          0x0A
+#define    RC_REPLY_STATUS_PROGRESS_REPORT            0x80
+
+
+/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/
+
+#define    RC_DS_SUCCESS                        0x0000
+#define    RC_DS_BAD_KEY                        0x0001
+#define    RC_DS_CHAIN_BUFFER_TOO_LARGE         0x0002
+#define    RC_DS_DEVICE_BUSY                    0x0003
+#define    RC_DS_DEVICE_LOCKED                  0x0004
+#define    RC_DS_DEVICE_NOT_AVAILABLE           0x0005
+#define    RC_DS_DEVICE_RESET                   0x0006
+#define    RC_DS_INAPPROPRIATE_FUNCTION         0x0007
+#define    RC_DS_INSUFFICIENT_RESOURCE_HARD     0x0008
+#define    RC_DS_INSUFFICIENT_RESOURCE_SOFT     0x0009
+#define    RC_DS_INVALID_INITIATOR_ADDRESS      0x000A
+#define    RC_DS_INVALID_MESSAGE_FLAGS          0x000B
+#define    RC_DS_INVALID_OFFSET                 0x000C
+#define    RC_DS_INVALID_PARAMETER              0x000D
+#define    RC_DS_INVALID_REQUEST                0x000E
+#define    RC_DS_INVALID_TARGET_ADDRESS         0x000F
+#define    RC_DS_MESSAGE_TOO_LARGE              0x0010
+#define    RC_DS_MESSAGE_TOO_SMALL              0x0011
+#define    RC_DS_MISSING_PARAMETER              0x0012
+#define    RC_DS_NO_SUCH_PAGE                   0x0013
+#define    RC_DS_REPLY_BUFFER_FULL              0x0014
+#define    RC_DS_TCL_ERROR                      0x0015
+#define    RC_DS_TIMEOUT                        0x0016
+#define    RC_DS_UNKNOWN_ERROR                  0x0017
+#define    RC_DS_UNKNOWN_FUNCTION               0x0018
+#define    RC_DS_UNSUPPORTED_FUNCTION           0x0019
+#define    RC_DS_UNSUPPORTED_VERSION            0x001A
+
+ /* msg header defines for VersionOffset */
+#define RCMSGVER_1   0x0001
+#define SGL_OFFSET_0    RCMSGVER_1
+#define SGL_OFFSET_4    (0x0040 | RCMSGVER_1)
+#define TRL_OFFSET_5    (0x0050 | RCMSGVER_1)
+#define TRL_OFFSET_6    (0x0060 | RCMSGVER_1)
+
+ /* msg header defines for MsgFlags */
+#define MSG_STATIC      0x0100
+#define MSG_64BIT_CNTXT 0x0200
+#define MSG_MULTI_TRANS 0x1000
+#define MSG_FAIL        0x2000
+#define MSG_LAST        0x4000
+#define MSG_REPLY       0x8000
+
+  /* normal LAN request message MsgFlags and VersionOffset (0x1041) */
+#define LAN_MSG_REQST  (MSG_MULTI_TRANS | SGL_OFFSET_4)
+
+ /* minimum size msg */
+#define THREE_WORD_MSG_SIZE 0x00030000
+#define FOUR_WORD_MSG_SIZE  0x00040000
+#define FIVE_WORD_MSG_SIZE  0x00050000
+#define SIX_WORD_MSG_SIZE   0x00060000
+#define SEVEN_WORD_MSG_SIZE 0x00070000
+#define EIGHT_WORD_MSG_SIZE 0x00080000
+#define NINE_WORD_MSG_SIZE  0x00090000
+
+/* Special TID Assignments */
+
+#define ADAPTER_TID   0
+#define HOST_TID  1
+
+ /* RedCreek private message codes */
+#define RC_PRIVATE_GET_MAC_ADDR     0x0001/**/ /* OBSOLETE */
+#define RC_PRIVATE_SET_MAC_ADDR     0x0002
+#define RC_PRIVATE_GET_LAN_STATS    0x0003
+#define RC_PRIVATE_GET_LINK_STATUS  0x0004
+#define RC_PRIVATE_SET_LINK_SPEED   0x0005
+#define RC_PRIVATE_SET_IP_AND_MASK  0x0006
+/* #define RC_PRIVATE_GET_IP_AND_MASK  0x0007 */ /* OBSOLETE */
+#define RC_PRIVATE_GET_LINK_SPEED   0x0008
+#define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
+/* #define RC_PRIVATE_GET_MAC_ADDR     0x000A *//**/
+#define RC_PRIVATE_GET_IP_AND_MASK  0x000B /**/
+#define RC_PRIVATE_DEBUG_MSG        0x000C
+#define RC_PRIVATE_REPORT_DRIVER_CAPABILITY  0x000D
+
+#define RC_PRIVATE_REBOOT           0x00FF
+
+
+/* RC message header */
+typedef struct _RC_MSG_FRAME 
+{
+   U8                          VersionOffset;
+   U8                          MsgFlags;
+   U16                         MessageSize;
+   BF                          TargetAddress:TID_SZ;
+   BF                          InitiatorAddress:TID_SZ;
+   BF                          Function:FUNCTION_SZ;
+   U32                         InitiatorContext;
+   /* SGL[] */ 
+}
+ RC_MSG_FRAME, *PRC_MSG_FRAME;
+
+
+ /* assumed a 16K minus 256 byte space for outbound queue message frames */
+#define MSG_FRAME_SIZE  512
+#define NMBR_MSG_FRAMES 30
+
+/*
+**  Message Unit CSR definitions for RedCreek PCI45 board
+*/
+typedef struct tag_rcatu 
+{
+    volatile unsigned long APICRegSel;  /* APIC Register Select */
+    volatile unsigned long reserved0;
+    volatile unsigned long APICWinReg;  /* APIC Window Register */
+    volatile unsigned long reserved1;
+    volatile unsigned long InMsgReg0;   /* inbound message register 0 */
+    volatile unsigned long InMsgReg1;   /* inbound message register 1 */
+    volatile unsigned long OutMsgReg0;  /* outbound message register 0 */
+    volatile unsigned long OutMsgReg1;  /* outbound message register 1 */
+    volatile unsigned long InDoorReg;   /* inbound doorbell register */
+    volatile unsigned long InIntStat;   /* inbound interrupt status register */
+    volatile unsigned long InIntMask;   /* inbound interrupt mask register */
+    volatile unsigned long OutDoorReg;  /* outbound doorbell register */
+    volatile unsigned long OutIntStat;  /* outbound interrupt status register */
+    volatile unsigned long OutIntMask;  /* outbound interrupt mask register */
+    volatile unsigned long reserved2;
+    volatile unsigned long reserved3;
+    volatile unsigned long InQueue;     /* inbound queue port */
+    volatile unsigned long OutQueue;    /* outbound queue port */
+    volatile unsigned long reserved4;
+    volatile unsigned long reserver5;
+     /* RedCreek extension */
+    volatile unsigned long EtherMacLow;
+    volatile unsigned long EtherMacHi;
+    volatile unsigned long IPaddr;
+    volatile unsigned long IPmask;
+}
+ ATU, *PATU;
+
+ /* 
+ ** typedef PAB
+ **
+ ** PCI Adapter Block - holds instance specific information and is located
+ ** in a reserved space at the start of the message buffer allocated by user.
+ */
+typedef struct
+{
+    PATU             p_atu;                /* ptr to  ATU register block */
+    PU8              pPci45LinBaseAddr;
+    PU8              pLinOutMsgBlock;
+    U32              outMsgBlockPhyAddr; 
+    PFNTXCALLBACK    pTransCallbackFunc;
+    PFNRXCALLBACK    pRecvCallbackFunc;
+    PFNCALLBACK      pRebootCallbackFunc;
+    PFNCALLBACK      pCallbackFunc;
+    U16              ADAPTERState;
+    U16              InboundMFrameSize;
+}
+ PAB, *PPAB;
+
+ /* 
+ ** in reserved space right after PAB in host memory is area for returning
+ ** values from card 
+ */
+
+ /* 
+ ** Array of pointers to PCI Adapter Blocks.
+ ** Indexed by a zero based (0-31) interface number.
+ */ 
+#define MAX_ADAPTERS 32
+static PPAB  PCIAdapterBlock[MAX_ADAPTERS] = 
+{
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+/*
+** typedef NICSTAT
+**
+** Data structure for NIC statistics retruned from PCI card.  Data copied from
+** here to user allocated RCLINKSTATS (see rclanmtl.h) structure.
+*/
+typedef struct tag_NicStat 
+{
+        unsigned long   TX_good; 
+        unsigned long   TX_maxcol;
+        unsigned long   TX_latecol;
+        unsigned long   TX_urun;
+        unsigned long   TX_crs;         /* lost carrier sense */
+        unsigned long   TX_def;         /* transmit deferred */
+        unsigned long   TX_singlecol;   /* single collisions */
+        unsigned long   TX_multcol;
+        unsigned long   TX_totcol;
+        unsigned long   Rcv_good;
+        unsigned long   Rcv_CRCerr;
+        unsigned long   Rcv_alignerr;
+        unsigned long   Rcv_reserr;     /* rnr'd pkts */
+        unsigned long   Rcv_orun;
+        unsigned long   Rcv_cdt;
+        unsigned long   Rcv_runt;
+        unsigned long   dump_status;    /* last field directly from the chip */
+} 
+ NICSTAT, *P_NICSTAT;
+ 
+
+#define DUMP_DONE   0x0000A005      /* completed statistical dump */
+#define DUMP_CLEAR  0x0000A007      /* completed stat dump and clear counters */
+
+
+static volatile int msgFlag;
+
+
+/* local function prototypes */
+static void ProcessOutboundAdapterMsg(PPAB pPab, U32 phyMsgAddr);
+static int FillAdapterMsgSGLFromTCB(PU32 pMsg, PRCTCB pXmitCntrlBlock);
+static int GetAdapterStatus(PPAB pPab);
+static int SendAdapterOutboundQInitMsg(PPAB pPab);
+static int SendEnableSysMsg(PPAB pPab);
+
+
+ /* 1st 100h bytes of message block is reserved for messenger instance */
+#define ADAPTER_BLOCK_RESERVED_SPACE 0x100
+
+/*
+** =========================================================================
+** InitRCApiMsgLayer()
+**
+** Initialize the RedCreek API Module and adapter.
+**
+** Inputs:  AdapterID - interface number from 0 to 15
+**          pciBaseAddr - virual base address of PCI (set by BIOS)
+**          p_msgbuf - virual address to private message block (min. 16K)
+**          p_phymsgbuf - physical address of private message block
+**          TransmitCallbackFunction - address of transmit callback function
+**          ReceiveCallbackFunction  - address of receive  callback function
+**
+** private message block is allocated by user.  It must be in locked pages.
+** p_msgbuf and p_phymsgbuf point to the same location.  Must be contigous
+** memory block of a minimum of 16K byte and long word aligned.
+** =========================================================================
+*/
+RC_RETURN
+InitRCApiMsgLayer(U16 AdapterID, U32 pciBaseAddr, 
+                  PU8 p_msgbuf,  PU8 p_phymsgbuf,
+                  PFNTXCALLBACK  TransmitCallbackFunction,
+                  PFNRXCALLBACK  ReceiveCallbackFunction,
+                  PFNCALLBACK    RebootCallbackFunction)
+{
+     int result;
+     PPAB pPab; 
+    
+#ifdef DEBUG
+     kprintf("InitAPI: Adapter:0x%04.4ux ATU:0x%08.8ulx msgbuf:0x%08.8ulx phymsgbuf:0x%08.8ulx\n"
+             "TransmitCallbackFunction:0x%08.8ulx  ReceiveCallbackFunction:0x%08.8ulx\n",
+             AdapterID, pciBaseAddr, p_msgbuf, p_phymsgbuf, TransmitCallbackFunction, ReceiveCallbackFunction);
+#endif /* DEBUG */
+
+    
+     /* Check if this interface already initialized - if so, shut it down */
+     if (PCIAdapterBlock[AdapterID] != NULL)
+     {
+          printk("PCIAdapterBlock[%d]!=NULL\n", AdapterID);
+//        RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+          PCIAdapterBlock[AdapterID] = NULL;
+     }
+
+    /* 
+    ** store adapter instance values in adapter block.
+    ** Adapter block is at beginning of message buffer
+    */  
+    pPab = (PPAB)p_msgbuf;
+    
+    pPab->p_atu = (PATU)pciBaseAddr;
+    pPab->pPci45LinBaseAddr =  (PU8)pciBaseAddr;
+    
+     /* Set outbound message frame addr - skip over Adapter Block */
+    pPab->outMsgBlockPhyAddr = (U32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+    pPab->pLinOutMsgBlock    = (PU8)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+
+     /* store callback function addresses */
+    pPab->pTransCallbackFunc = TransmitCallbackFunction;
+    pPab->pRecvCallbackFunc  = ReceiveCallbackFunction;
+    pPab->pRebootCallbackFunc  = RebootCallbackFunction;
+    pPab->pCallbackFunc  = (PFNCALLBACK)NULL;
+
+    /*
+    ** Initialize API 
+    */
+    result = GetAdapterStatus(pPab);
+    
+    if (result != RC_RTN_NO_ERROR)
+        return result;
+
+    if (pPab->ADAPTERState == ADAPTER_STATE_OPERATIONAL)
+    {
+         printk("pPab->ADAPTERState == op: resetting adapter\n");
+         RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+    }
+        
+    result = SendAdapterOutboundQInitMsg(pPab);
+    
+    if (result != RC_RTN_NO_ERROR)
+         return result;
+
+    result = SendEnableSysMsg(pPab);
+   
+    if (result != RC_RTN_NO_ERROR)
+         return result;
+   
+    PCIAdapterBlock[AdapterID] = pPab;
+    return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** Disable and Enable Adapter interrupts.  Adapter interrupts are enabled at Init time
+** but can be disabled and re-enabled through these two function calls.
+** Packets will still be put into any posted received buffers and packets will
+** be sent through RCSendPacket() functions.  Disabling Adapter interrupts
+** will prevent hardware interrupt to host even though the outbound Adapter msg
+** queue is not emtpy.
+** =========================================================================
+*/
+#define i960_OUT_POST_Q_INT_BIT        0x0008 /* bit set masks interrupts */
+
+RC_RETURN RCDisableAdapterInterrupts(U16 AdapterID)
+{
+    PPAB pPab;
+
+
+    pPab = PCIAdapterBlock[AdapterID];
+    
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+        
+    pPab->p_atu->OutIntMask |= i960_OUT_POST_Q_INT_BIT;
+
+    return RC_RTN_NO_ERROR;
+}
+
+RC_RETURN RCEnableAdapterInterrupts(U16 AdapterID)
+{
+    PPAB pPab;
+
+    pPab = PCIAdapterBlock[AdapterID];
+    
+    if (pPab == NULL)
+         return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    pPab->p_atu->OutIntMask &= ~i960_OUT_POST_Q_INT_BIT;
+    
+    return RC_RTN_NO_ERROR;
+
+}
+
+
+/*
+** =========================================================================
+** RCSendPacket()
+** =========================================================================
+*/
+RC_RETURN
+RCSendPacket(U16 AdapterID, U32 InitiatorContext, PRCTCB pTransCtrlBlock)
+{
+    U32 msgOffset;
+    PU32 pMsg;
+    int size;
+    PPAB pPab;
+
+#ifdef DEBUG
+kprintf("RCSendPacket()...\n");
+#endif /* DEBUG */
+    
+    pPab = PCIAdapterBlock[AdapterID];
+
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+     /* get Inbound free Q entry - reading from In Q gets free Q entry */
+     /* offset to Msg Frame in PCI msg block */
+
+    msgOffset = pPab->p_atu->InQueue; 
+
+    if (msgOffset == 0xFFFFFFFF)
+    {
+#ifdef DEBUG
+        kprintf("RCSendPacket(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+        return RC_RTN_FREE_Q_EMPTY;
+    }
+        
+     /* calc virual address of msg - virual already mapped to physical */    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+    size = FillAdapterMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
+
+    if (size == -1) /* error processing TCB - send NOP msg */
+    {
+#ifdef DEBUG
+            kprintf("RCSendPacket(): Error Rrocess TCB!\n");
+#endif /* DEBUG */
+        pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+        pMsg[1] = UTIL_NOP << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+        return RC_RTN_TCB_ERROR;
+    }
+    else /* send over msg header */
+    {    
+        pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
+        pMsg[1] = LAN_PACKET_SEND << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+        pMsg[2] = InitiatorContext;
+        pMsg[3] = 0;  /* batch reply */
+         /* post to Inbound Post Q */   
+        pPab->p_atu->InQueue = msgOffset;
+        return RC_RTN_NO_ERROR;
+    }
+}
+ 
+
+/*
+** =========================================================================
+** RCPostRecvBuffer()
+**
+** inputs:  pBufrCntrlBlock - pointer to buffer control block
+**
+** returns TRUE if successful in sending message, else FALSE.
+** =========================================================================
+*/
+RC_RETURN
+RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransCtrlBlock)
+{
+    U32 msgOffset;
+    PU32 pMsg;
+    int size;
+    PPAB pPab;
+
+#ifdef DEBUG
+kprintf("RCPostRecvBuffers()...\n");
+#endif /* DEBUG */
+    
+     /* search for DeviceHandle */
+    pPab = PCIAdapterBlock[AdapterID];
+
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+
+     /* get Inbound free Q entry - reading from In Q gets free Q entry */
+     /* offset to Msg Frame in PCI msg block */
+    msgOffset = pPab->p_atu->InQueue; 
+
+    if (msgOffset == 0xFFFFFFFF)
+    {
+#ifdef DEBUG
+            kprintf("RCPostRecvBuffers(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+        return RC_RTN_FREE_Q_EMPTY;
+   
+    }
+     /* calc virual address of msg - virual already mapped to physical */    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+    size = FillAdapterMsgSGLFromTCB(pMsg + 4, pTransCtrlBlock);
+
+    if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */
+    {
+#ifdef DEBUG
+        kprintf("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
+#endif /* DEBUG */
+        pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
+        pMsg[1] = UTIL_NOP << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+         /* post to Post Q */   
+        pPab->p_atu->InQueue = msgOffset;
+        return RC_RTN_TCB_ERROR;
+    }
+    else /* send over size msg header */
+    {    
+        pMsg[0] = (size + 4) << 16 | LAN_MSG_REQST; /* send over message size and flags */
+        pMsg[1] = LAN_RECEIVE_POST << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+        pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+        pMsg[3] = *(PU32)pTransCtrlBlock; /* number of packet buffers */
+         /* post to Post Q */   
+        pPab->p_atu->InQueue = msgOffset;
+        return RC_RTN_NO_ERROR;
+    }
+}
+
+
+/*
+** =========================================================================
+** RCProcMsgQ()
+**
+** Process outbound message queue until empty.
+** =========================================================================
+*/
+void 
+RCProcMsgQ(U16 AdapterID)
+{
+    U32 phyAddrMsg;
+    PU8 p8Msg;
+    PU32 p32;
+    U16 count;
+    PPAB pPab;
+    unsigned char debug_msg[20];
+    
+    pPab = PCIAdapterBlock[AdapterID];
+    
+    if (pPab == NULL)
+        return;
+    
+    phyAddrMsg = pPab->p_atu->OutQueue;
+
+    while (phyAddrMsg != 0xFFFFFFFF)
+    {
+        p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+        p32 = (PU32)p8Msg;
+        
+        //printk(" msg: 0x%x  0x%x \n", p8Msg[7], p32[5]);
+
+     /* 
+     ** Send Packet Reply Msg
+     */
+        if (LAN_PACKET_SEND == p8Msg[7])  /* function code byte */
+        {
+            count = *(PU16)(p8Msg+2);
+            count -= p8Msg[0] >> 4;
+                                      /* status, count, context[], adapter */
+           (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, AdapterID);
+        }             
+     /* 
+     ** Receive Packet Reply Msg */
+        else if (LAN_RECEIVE_POST == p8Msg[7])
+        {
+#ifdef DEBUG    
+    kprintf("RECV_REPLY pPab:0x%08.8ulx p8Msg:0x%08.8ulx p32:0x%08.8ulx\n", pPab, p8Msg, p32);
+    kprintf("msg: 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+            p32[0], p32[1], p32[2], p32[3]);
+    kprintf("     0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+            p32[4], p32[5], p32[6], p32[7]);
+    kprintf("     0x%08.8ulx:0X%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+            p32[8], p32[9], p32[10], p32[11]);
+#endif
+               /*  status, count, buckets remaining, packetParmBlock, adapter */
+          (*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, AdapterID);
+      
+      
+        }
+        else if (LAN_RESET == p8Msg[7] || LAN_SHUTDOWN == p8Msg[7])
+        {
+            if (pPab->pCallbackFunc)
+            {
+                (*pPab->pCallbackFunc)(p8Msg[19],0,0,AdapterID);
+            }
+            else
+            {
+                pPab->pCallbackFunc = (PFNCALLBACK) 1;
+            }
+            //PCIAdapterBlock[AdapterID] = 0;
+        }
+        else if (RC_PRIVATE == p8Msg[7])
+        {
+            //printk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
+          switch (p32[5])
+          {
+          case RC_PRIVATE_DEBUG_MSG:
+               msgFlag = 1;
+               /*printk("Received RC_PRIVATE msg\n");*/
+               debug_msg[15]  = (p32[6]&0xff000000) >> 24;
+               debug_msg[14]  = (p32[6]&0x00ff0000) >> 16;
+               debug_msg[13]  = (p32[6]&0x0000ff00) >> 8;
+               debug_msg[12]  = (p32[6]&0x000000ff);
+
+               debug_msg[11]  = (p32[7]&0xff000000) >> 24;
+               debug_msg[10]  = (p32[7]&0x00ff0000) >> 16;
+               debug_msg[ 9]  = (p32[7]&0x0000ff00) >> 8;
+               debug_msg[ 8]  = (p32[7]&0x000000ff);
+
+               debug_msg[ 7]  = (p32[8]&0xff000000) >> 24;
+               debug_msg[ 6]  = (p32[8]&0x00ff0000) >> 16;
+               debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8;
+               debug_msg[ 4] = (p32[8]&0x000000ff);
+
+               debug_msg[ 3] = (p32[9]&0xff000000) >> 24;
+               debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16;
+               debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8;
+               debug_msg[ 0] = (p32[9]&0x000000ff);
+
+               debug_msg[16] = '\0';
+               printk (debug_msg);
+               break;
+          case RC_PRIVATE_REBOOT:
+               printk("Adapter reboot initiated...\n");
+               if (pPab->pRebootCallbackFunc)
+               {
+                    (*pPab->pRebootCallbackFunc)(0,0,0,AdapterID);
+               }
+               break;
+          default:
+                printk("Unknown private msg received: 0x%x\n",
+                      p32[5]);
+               break;
+          }
+        }
+
+     /* 
+     ** Process other Msg's
+     */
+        else
+        {
+            ProcessOutboundAdapterMsg(pPab, phyAddrMsg);
+        }
+        
+         /* return MFA to outbound free Q*/
+        pPab->p_atu->OutQueue = phyAddrMsg;
+    
+         /* any more msgs? */
+        phyAddrMsg = pPab->p_atu->OutQueue;
+    }
+}
+
+
+/*
+** =========================================================================
+**  Returns LAN interface statistical counters to space provided by caller at
+**  StatsReturnAddr.  Returns 0 if success, else RC_RETURN code.
+**  This function will call the WaitCallback function provided by
+**  user while waiting for card to respond.
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkStatistics(U16 AdapterID, 
+                    P_RCLINKSTATS StatsReturnAddr,
+                    PFNWAITCALLBACK WaitCallback)
+{
+    U32 msgOffset;
+    volatile U32 timeout;
+    volatile PU32 pMsg;
+    volatile PU32 p32, pReturnAddr;
+    P_NICSTAT pStats;
+    int i;
+    PPAB pPab;
+
+/*kprintf("Get82558Stats() StatsReturnAddr:0x%08.8ulx\n", StatsReturnAddr);*/
+
+    pPab = PCIAdapterBlock[AdapterID];
+
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    msgOffset = pPab->p_atu->InQueue;
+
+    if (msgOffset == 0xFFFFFFFF)
+    {
+    #ifdef DEBUG
+        kprintf("Get8255XStats(): Inbound Free Q empty!\n");
+    #endif
+        return RC_RTN_FREE_Q_EMPTY;
+    }
+
+     /* calc virual address of msg - virual already mapped to physical */
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+/*dprintf("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintf("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+
+    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+    pMsg[3] = 0x112; /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LAN_STATS;
+    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+
+    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+
+    pStats = (P_NICSTAT)p32;
+    pStats->dump_status = 0xFFFFFFFF;
+
+     /* post to Inbound Post Q */
+    pPab->p_atu->InQueue = msgOffset;
+
+    timeout = 100000;
+    while (1)
+    {
+        if (WaitCallback)
+                (*WaitCallback)();
+        
+        for (i = 0; i < 1000; i++)
+            ;
+
+        if (pStats->dump_status != 0xFFFFFFFF)
+            break;
+
+        if (!timeout--)
+        {
+        #ifdef DEBUG
+            kprintf("RCGet82558Stats() Timeout waiting for NIC statistics\n");
+        #endif
+            return RC_RTN_MSG_REPLY_TIMEOUT;
+        }
+    }
+    
+    pReturnAddr = (PU32)StatsReturnAddr;
+    
+     /* copy Nic stats to user's structure */
+    for (i = 0; i < (int) sizeof(RCLINKSTATS) / 4; i++)
+        pReturnAddr[i] = p32[i];
+   
+    return RC_RTN_NO_ERROR;     
+}
+
+
+/*
+** =========================================================================
+** Get82558LinkStatus()
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkStatus(U16 AdapterID, PU32 ReturnAddr, PFNWAITCALLBACK WaitCallback)
+{
+    U32 msgOffset;
+    volatile U32 timeout;
+    volatile PU32 pMsg;
+    volatile PU32 p32;
+    PPAB pPab;
+
+/*kprintf("Get82558LinkStatus() ReturnPhysAddr:0x%08.8ulx\n", ReturnAddr);*/
+
+    pPab = PCIAdapterBlock[AdapterID];
+
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    msgOffset = pPab->p_atu->InQueue;
+
+    if (msgOffset == 0xFFFFFFFF)
+    {
+    #ifdef DEBUG
+        dprintf("Get82558LinkStatus(): Inbound Free Q empty!\n");
+    #endif
+        return RC_RTN_FREE_Q_EMPTY;
+    }
+
+     /* calc virual address of msg - virual already mapped to physical */
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+/*dprintf("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintf("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+
+    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+    pMsg[3] = 0x112; /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
+    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+
+    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    *p32 = 0xFFFFFFFF;
+    
+     /* post to Inbound Post Q */
+    pPab->p_atu->InQueue = msgOffset;
+
+    timeout = 100000;
+    while (1)
+    {
+        U32 i;
+
+        if (WaitCallback)
+                (*WaitCallback)();
+        
+        for (i = 0; i < 1000; i++)
+            ;
+
+        if (*p32 != 0xFFFFFFFF)
+            break;
+
+        if (!timeout--)
+        {
+        #ifdef DEBUG
+            kprintf("Timeout waiting for link status\n");
+        #endif    
+            return RC_RTN_MSG_REPLY_TIMEOUT;
+        }
+    }
+    
+    *ReturnAddr = *p32; /* 1 = up 0 = down */
+    
+    return RC_RTN_NO_ERROR;
+    
+}
+
+/*
+** =========================================================================
+** RCGetMAC()
+**
+** get the MAC address the adapter is listening for in non-promiscous mode.
+** MAC address is in media format.
+** =========================================================================
+*/
+RC_RETURN
+RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback)
+{
+     unsigned i, timeout;
+     U32      off;
+     PU32     p;
+     U32      temp[2];
+     PPAB     pPab;
+     PATU     p_atu;
+    
+     pPab = PCIAdapterBlock[AdapterID];
+    
+     if (pPab == NULL)
+          return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+     p_atu = pPab->p_atu;
+
+     p_atu->EtherMacLow = 0;     /* first zero return data */
+     p_atu->EtherMacHi = 0;
+    
+     off = p_atu->InQueue;   /* get addresss of message */
+ 
+     if (0xFFFFFFFF == off)
+          return RC_RTN_FREE_Q_EMPTY;
+
+     p = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+#ifdef RCDEBUG
+     printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
+            (uint)p_atu, (uint)off, (uint)p);
+#endif /* RCDEBUG */
+     /* setup private message */
+     p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+     p[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+     p[2] = 0;               /* initiator context */
+     p[3] = 0x218;           /* transaction context */
+     p[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_MAC_ADDR;
+
+
+     p_atu->InQueue = off;   /* send it to the device */
+#ifdef RCDEBUG
+     printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
+            (uint)p_atu, (uint)off, (uint)p);
+#endif /* RCDEBUG */
+
+     /* wait for the rcpci45 board to update the info */
+     timeout = 1000000;
+     while (0 == p_atu->EtherMacLow) 
+     {
+          if (WaitCallback)
+               (*WaitCallback)();
+    
+          for (i = 0; i < 1000; i++)
+               ;
+
+          if (!timeout--)
+          {
+               printk("rc_getmac: Timeout\n");
+               return RC_RTN_MSG_REPLY_TIMEOUT;
+          }
+     }
+    
+     /* read the mac address  */
+     temp[0] = p_atu->EtherMacLow;
+     temp[1] = p_atu->EtherMacHi;
+     memcpy((char *)mac, (char *)temp, 6);
+
+
+#ifdef RCDEBUG
+//    printk("rc_getmac: 0x%X\n", ptr);
+#endif /* RCDEBUG */
+
+     return RC_RTN_NO_ERROR;
+}
+
+ 
+/*
+** =========================================================================
+** RCSetMAC()
+**
+** set MAC address the adapter is listening for in non-promiscous mode.
+** MAC address is in media format.
+** =========================================================================
+*/
+RC_RETURN
+RCSetMAC(U16 AdapterID, PU8 mac)
+{
+    U32  off;
+    PU32 pMsg;
+    PPAB pPab;
+
+
+    pPab = PCIAdapterBlock[AdapterID];
+    
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    off = pPab->p_atu->InQueue; /* get addresss of message */
+    
+    if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+    /* setup private message */
+    pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = 0;                 /* initiator context */
+    pMsg[3] = 0x219;             /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_MAC_ADDR;
+    pMsg[5] = *(unsigned *)mac;  /* first four bytes */
+    pMsg[6] = *(unsigned *)(mac + 4); /* last two bytes */
+    
+    pPab->p_atu->InQueue = off;   /* send it to the device */
+
+    return RC_RTN_NO_ERROR ;
+}
+
+
+/*
+** =========================================================================
+** RCSetLinkSpeed()
+**
+** set ethernet link speed. 
+** input: speedControl - determines action to take as follows
+**          0 = reset and auto-negotiate (NWay)
+**          1 = Full Duplex 100BaseT
+**          2 = Half duplex 100BaseT
+**          3 = Full Duplex  10BaseT
+**          4 = Half duplex  10BaseT
+**          all other values are ignore (do nothing)
+** =========================================================================
+*/
+RC_RETURN
+RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode)
+{
+    U32  off;
+    PU32 pMsg;
+    PPAB pPab;
+
+    
+    pPab =PCIAdapterBlock[AdapterID];
+     
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    off = pPab->p_atu->InQueue; /* get addresss of message */
+    
+    if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+    /* setup private message */
+    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = 0;                 /* initiator context */
+    pMsg[3] = 0x219;             /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_LINK_SPEED;
+    pMsg[5] = LinkSpeedCode;     /* link speed code */
+
+    pPab->p_atu->InQueue = off;   /* send it to the device */
+
+    return RC_RTN_NO_ERROR ;
+}
+
+/*
+** =========================================================================
+** RCGetLinkSpeed()
+**
+** get ethernet link speed. 
+**
+** 0 = Unknown
+** 1 = Full Duplex 100BaseT
+** 2 = Half duplex 100BaseT
+** 3 = Full Duplex  10BaseT
+** 4 = Half duplex  10BaseT
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
+{
+     U32 msgOffset, timeout;
+     PU32 pMsg;
+     volatile PU32 p32;
+     U8 AdapterLinkSpeed;
+     PPAB pPab;
+
+     pPab =PCIAdapterBlock[AdapterID];
+
+
+     msgOffset = pPab->p_atu->InQueue;
+
+
+     if (msgOffset == 0xFFFFFFFF)
+     {
+          kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+          return RC_RTN_FREE_Q_EMPTY;
+     }
+
+     /* calc virtual address of msg - virtual already mapped to physical */    
+     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+     /* virtual pointer to return buffer - clear first two dwords */
+     p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+     p32[0] = 0xff;
+
+     /* setup private message */
+     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+     pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+     pMsg[2] = 0;                 /* initiator context */
+     pMsg[3] = 0x219;             /* transaction context */
+     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
+     /* phys address to return status - area right after PAB */
+     pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+   
+     /* post to Inbound Post Q */   
+
+     pPab->p_atu->InQueue = msgOffset;
+
+     /* wait for response */
+     timeout = 1000000;
+     while(1)
+     {
+          int i;
+        
+          if (WaitCallback)
+                (*WaitCallback)();
+
+          for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
+               ;
+            
+          if (p32[0] != 0xff)
+               break;
+            
+          if (!timeout--)
+          {
+               kprintf("Timeout waiting for link speed from adapter\n");
+               kprintf("0x%08.8ulx\n", p32[0]);
+               return RC_RTN_NO_LINK_SPEED;
+          }
+     }
+
+     /* get Link speed */
+     AdapterLinkSpeed = (U8)((volatile PU8)p32)[0] & 0x0f;
+
+     *pLinkSpeedCode= AdapterLinkSpeed;
+
+     return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCReportDriverCapability(U16 AdapterID, U32 capability)
+**
+** Currently defined bits:
+** WARM_REBOOT_CAPABLE   0x01
+**
+** =========================================================================
+*/
+RC_RETURN
+RCReportDriverCapability(U16 AdapterID, U32 capability)
+{
+    U32  off;
+    PU32 pMsg;
+    PPAB pPab;
+
+    pPab =PCIAdapterBlock[AdapterID];
+     
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    off = pPab->p_atu->InQueue; /* get addresss of message */
+    
+    if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+    /* setup private message */
+    pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = 0;                 /* initiator context */
+    pMsg[3] = 0x219;             /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_REPORT_DRIVER_CAPABILITY;
+    pMsg[5] = capability;
+
+    pPab->p_atu->InQueue = off;   /* send it to the device */
+
+    return RC_RTN_NO_ERROR ;
+}
+
+/*
+** =========================================================================
+** RCGetFirmwareVer()
+**
+** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
+**
+** =========================================================================
+*/
+RC_RETURN
+RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback)
+{
+     U32 msgOffset, timeout;
+     PU32 pMsg;
+     volatile PU32 p32;
+     PPAB pPab;
+
+     pPab =PCIAdapterBlock[AdapterID];
+
+     msgOffset = pPab->p_atu->InQueue;
+
+
+     if (msgOffset == 0xFFFFFFFF)
+     {
+          kprintf("RCGetFirmwareVer(): Inbound Free Q empty!\n");
+          return RC_RTN_FREE_Q_EMPTY;
+     }
+
+     /* calc virtual address of msg - virtual already mapped to physical */    
+     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+     /* virtual pointer to return buffer - clear first two dwords */
+     p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+     p32[0] = 0xff;
+
+     /* setup private message */
+     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
+     pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+     pMsg[2] = 0;                 /* initiator context */
+     pMsg[3] = 0x219;             /* transaction context */
+     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
+     /* phys address to return status - area right after PAB */
+     pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+
+
+   
+     /* post to Inbound Post Q */   
+
+     pPab->p_atu->InQueue = msgOffset;
+
+    
+     /* wait for response */
+     timeout = 1000000;
+     while(1)
+     {
+          int i;
+        
+          if (WaitCallback)
+                (*WaitCallback)();
+            
+          for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
+               ;
+
+          if (p32[0] != 0xff)
+               break;
+            
+          if (!timeout--)
+          {
+               kprintf("Timeout waiting for link speed from adapter\n");
+               return RC_RTN_NO_FIRM_VER;
+          }
+     }
+
+     strcpy(pFirmString, (PU8)p32);
+     return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCResetLANCard()
+**
+** ResourceFlags indicates whether to return buffer resource explicitly
+** to host or keep and reuse.
+** CallbackFunction (if not NULL) is the function to be called when 
+** reset is complete.
+** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
+** reset is done (if not NULL).
+**
+** =========================================================================
+*/
+RC_RETURN 
+RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+    unsigned long off;
+    unsigned long *pMsg;
+    PPAB pPab;
+    int i;
+    long timeout = 0;
+
+    
+    pPab =PCIAdapterBlock[AdapterID];
+     
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+
+    off = pPab->p_atu->InQueue; /* get addresss of message */
+    
+    if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+    
+    pPab->pCallbackFunc = CallbackFunction;
+
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+    /* setup message */
+    pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = LAN_RESET << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+    pMsg[3] = ResourceFlags << 16;   /* resource flags */
+
+    pPab->p_atu->InQueue = off;   /* send it to the device */
+
+    if (CallbackFunction == (PFNCALLBACK)NULL)
+    {
+        /* call RCProcMsgQ() until something in pPab->pCallbackFunc
+           or until timer goes off */
+        while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
+        {
+            RCProcMsgQ(AdapterID);
+            for (i = 0; i < 100000; i++)     /* please don't hog the bus!!! */
+               ;
+            timeout++;
+            if (timeout > 10000)
+            {
+                break;
+            }
+        }
+        if (ReturnAddr != (PU32)NULL)
+           *ReturnAddr = (U32)pPab->pCallbackFunc;
+    }
+
+    return RC_RTN_NO_ERROR ;
+}
+/*
+** =========================================================================
+** RCResetAdapter()
+**
+** Send StatusGet Msg, wait for results return directly to buffer.
+**
+** =========================================================================
+*/
+RC_RETURN 
+RCResetAdapter(U16 AdapterID)
+{
+     U32 msgOffset, timeout;
+     PU32 pMsg;
+     PPAB pPab;
+     volatile PU32 p32;
+    
+     pPab = PCIAdapterBlock[AdapterID];
+     msgOffset = pPab->p_atu->InQueue;
+
+     if (msgOffset == 0xFFFFFFFF)
+     {
+          return RC_RTN_FREE_Q_EMPTY;
+     }
+
+     /* calc virtual address of msg - virtual already mapped to physical */    
+     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+     pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+     pMsg[1] = RC_CMD_ADAPTER_RESET << 24 | HOST_TID << 12 | ADAPTER_TID;
+     pMsg[2] = 0; /* universal context */
+     pMsg[3] = 0; /* universal context */
+     pMsg[4] = 0; /* universal context */
+     pMsg[5] = 0; /* universal context */
+     /* phys address to return status - area right after PAB */
+     pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+     pMsg[7] = 0;
+     pMsg[8] = 1;  /*  return 1 byte */
+
+     /* virual pointer to return buffer - clear first two dwords */
+     p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+     p32[0] = 0;
+     p32[1] = 0;
+
+     /* post to Inbound Post Q */   
+
+     pPab->p_atu->InQueue = msgOffset;
+
+     /* wait for response */
+     timeout = 1000000;
+     while(1)
+     {
+          int i;
+        
+          for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
+               ;
+            
+          if (p32[0] || p32[1])
+               break;
+            
+          if (!timeout--)
+          {
+               printk("RCResetAdapter timeout\n");
+               return RC_RTN_MSG_REPLY_TIMEOUT;
+          }
+     }
+     return RC_RTN_NO_ERROR;
+}
+
+/*
+** =========================================================================
+** RCShutdownLANCard()
+**
+** ResourceFlags indicates whether to return buffer resource explicitly
+** to host or keep and reuse.
+** CallbackFunction (if not NULL) is the function to be called when 
+** shutdown is complete.
+** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
+** shutdown is done (if not NULL).
+**
+** =========================================================================
+*/
+RC_RETURN 
+RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+{
+    volatile PU32 pMsg;
+    U32 off;
+    PPAB pPab;
+    int i;
+    long timeout = 0;
+
+    pPab = PCIAdapterBlock[AdapterID];
+
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+
+    off = pPab->p_atu->InQueue; /* get addresss of message */
+    
+    if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+
+    pPab->pCallbackFunc = CallbackFunction;
+    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+    /* setup message */
+    pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = LAN_SHUTDOWN << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+    pMsg[3] = ResourceFlags << 16;   /* resource flags */
+
+    pPab->p_atu->InQueue = off;   /* send it to the device */
+
+    if (CallbackFunction == (PFNCALLBACK)NULL)
+    {
+        /* call RCProcMsgQ() until something in pPab->pCallbackFunc
+           or until timer goes off */
+        while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
+        {
+            RCProcMsgQ(AdapterID);
+            for (i = 0; i < 100000; i++)     /* please don't hog the bus!!! */
+               ;
+            timeout++;
+            if (timeout > 10000)
+            {
+                break;
+            }
+        }
+        if (ReturnAddr != (PU32)NULL)
+           *ReturnAddr = (U32)pPab->pCallbackFunc;
+    }
+    return RC_RTN_NO_ERROR ;
+}
+
+
+/*
+** =========================================================================
+** RCSetRavlinIPandMask()
+**
+** Set the Ravlin 45/PCI cards IP address and network mask.
+**
+** IP address and mask must be in network byte order.
+** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+** 0x04030201 and 0x00FFFFFF on a little endian machine.
+**
+** =========================================================================
+*/
+RC_RETURN
+RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask)
+{
+    volatile PU32 pMsg;
+    U32 off;
+    PPAB pPab;
+
+    pPab = PCIAdapterBlock[AdapterID];
+
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+
+    off = pPab->p_atu->InQueue; /* get addresss of message */
+    
+    if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+    /* setup private message */
+    pMsg[0] = SEVEN_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = 0;                 /* initiator context */
+    pMsg[3] = 0x219;             /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_SET_IP_AND_MASK;
+    pMsg[5] = ipAddr; 
+    pMsg[6] = netMask;
+
+
+    pPab->p_atu->InQueue = off;   /* send it to the device */
+    return RC_RTN_NO_ERROR ;
+
+}
+
+/*
+** =========================================================================
+** RCGetRavlinIPandMask()
+**
+** get the IP address and MASK from the card
+** 
+** =========================================================================
+*/
+RC_RETURN
+RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask, 
+                        PFNWAITCALLBACK WaitCallback)
+{
+    unsigned i, timeout;
+    U32      off;
+    PU32     pMsg, p32;
+    PPAB     pPab;
+    PATU     p_atu;
+    
+#ifdef DEBUG
+    kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
+#endif /* DEBUG */
+
+    pPab = PCIAdapterBlock[AdapterID];
+    
+    if (pPab == NULL)
+        return RC_RTN_ADPTR_NOT_REGISTERED;
+    
+    p_atu = pPab->p_atu;
+    off = p_atu->InQueue;   /* get addresss of message */
+ 
+   if (0xFFFFFFFF == off)
+         return RC_RTN_FREE_Q_EMPTY;
+
+    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    *p32 = 0xFFFFFFFF;
+
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
+
+#ifdef DEBUG
+    kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
+#endif /* DEBUG */
+    /* setup private message */
+    pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_PRIVATE << 24 | HOST_TID << 12 | LAN_TARGET_ID;
+    pMsg[2] = 0;               /* initiator context */
+    pMsg[3] = 0x218;           /* transaction context */
+    pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
+    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+
+    p_atu->InQueue = off;   /* send it to the device */
+#ifdef DEBUG
+    kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
+#endif /* DEBUG */
+
+     /* wait for the rcpci45 board to update the info */
+    timeout = 100000;
+    while (0xffffffff == *p32)
+    {
+        if (WaitCallback)
+                (*WaitCallback)();
+    
+        for (i = 0; i < 1000; i++)
+            ;
+
+        if (!timeout--)
+        {
+        #ifdef DEBUG
+            kprintf("RCGetRavlinIPandMask: Timeout\n");
+        #endif /* DEBUG */
+             return RC_RTN_MSG_REPLY_TIMEOUT;
+        }
+    }
+
+#ifdef DEBUG
+    kprintf("RCGetRavlinIPandMask: after time out\n", \
+            "p32[0] (IpAddr) 0x%08.8ulx, p32[1] (IPmask) 0x%08.8ulx\n", p32[0], p32[1]);
+#endif /* DEBUG */
+    
+    /* send IP and mask to user's space  */
+    *pIpAddr  = p32[0];
+    *pNetMask = p32[1];
+
+
+#ifdef DEBUG
+    kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
+#endif /* DEBUG */
+
+    return RC_RTN_NO_ERROR;
+}
+
+/* 
+** /////////////////////////////////////////////////////////////////////////
+** /////////////////////////////////////////////////////////////////////////
+**
+**                        local functions
+**
+** /////////////////////////////////////////////////////////////////////////
+** /////////////////////////////////////////////////////////////////////////
+*/
+
+/*
+** =========================================================================
+** SendAdapterOutboundQInitMsg()
+**
+** =========================================================================
+*/
+static int 
+SendAdapterOutboundQInitMsg(PPAB pPab)
+{
+    U32 msgOffset, timeout, phyOutQFrames, i;
+    volatile PU32 pMsg;
+    volatile PU32 p32;
+    
+    
+    
+    msgOffset = pPab->p_atu->InQueue;
+
+    
+    if (msgOffset == 0xFFFFFFFF)
+    {
+#ifdef DEBUG
+        kprintf("SendAdapterOutboundQInitMsg(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+        return RC_RTN_FREE_Q_EMPTY;
+    }
+    
+    
+     /* calc virual address of msg - virual already mapped to physical */    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+#ifdef DEBUG
+kprintf("SendAdapterOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
+#endif /* DEBUG */
+
+    pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
+    pMsg[1] = RC_CMD_OUTBOUND_INIT << 24 | HOST_TID << 12 | ADAPTER_TID;
+    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+    pMsg[3] = 0x106; /* transaction context */
+    pMsg[4] = 4096; /* Host page frame size */
+    pMsg[5] = MSG_FRAME_SIZE  << 16 | 0x80; /* outbound msg frame size and Initcode */
+    pMsg[6] = 0xD0000004;       /* simple sgl element LE, EOB */
+     /* phys address to return status - area right after PAB */
+    pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+
+     /* virual pointer to return buffer - clear first two dwords */
+    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32[0] = 0;
+    
+     /* post to Inbound Post Q */   
+    pPab->p_atu->InQueue = msgOffset;
+    
+  /* wait for response */
+    timeout = 100000;
+    while(1)
+    {
+        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
+            ;
+            
+        if (p32[0])
+            break;
+            
+        if (!timeout--)
+        {
+#ifdef DEBUG
+            kprintf("Timeout wait for InitOutQ InPrgress status from adapter\n");
+#endif /* DEBUG */
+            return RC_RTN_NO_STATUS;
+        }
+    }
+
+    timeout = 100000;
+    while(1)
+    {
+        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
+            ;
+            
+        if (p32[0] == RC_CMD_OUTBOUND_INIT_COMPLETE)
+            break;
+
+        if (!timeout--)
+        {
+#ifdef DEBUG
+            kprintf("Timeout wait for InitOutQ Complete status from adapter\n");
+#endif /* DEBUG */
+            return RC_RTN_NO_STATUS;
+        }
+    }
+
+     /* load PCI outbound free Q with MF physical addresses */
+    phyOutQFrames = pPab->outMsgBlockPhyAddr;
+
+    for (i = 0; i < NMBR_MSG_FRAMES; i++)
+    {
+        pPab->p_atu->OutQueue = phyOutQFrames;
+        phyOutQFrames += MSG_FRAME_SIZE;
+    }
+    return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** GetAdapterStatus()
+**
+** Send StatusGet Msg, wait for results return directly to buffer.
+**
+** =========================================================================
+*/
+static int 
+GetAdapterStatus(PPAB pPab)
+{
+    U32 msgOffset, timeout;
+    PU32 pMsg;
+    volatile PU32 p32;
+    
+    
+    msgOffset = pPab->p_atu->InQueue; 
+    printk("GetAdapterStatus: msg offset = 0x%x\n", msgOffset);
+    if (msgOffset == 0xFFFFFFFF)
+    {
+#ifdef DEBUG
+        kprintf("GetAdapterStatus(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+        return RC_RTN_FREE_Q_EMPTY;
+    }
+
+     /* calc virual address of msg - virual already mapped to physical */    
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+    pMsg[0] = NINE_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_CMD_STATUS_GET << 24 | HOST_TID << 12 | ADAPTER_TID;
+    pMsg[2] = 0; /* universal context */
+    pMsg[3] = 0; /* universal context */
+    pMsg[4] = 0; /* universal context */
+    pMsg[5] = 0; /* universal context */
+     /* phys address to return status - area right after PAB */
+    pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[7] = 0;
+    pMsg[8] = 88;  /*  return 88 bytes */
+
+     /* virual pointer to return buffer - clear first two dwords */
+    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32[0] = 0;
+    p32[1] = 0;
+
+#ifdef DEBUG
+kprintf("GetAdapterStatus - pMsg:0x%08.8ulx, msgOffset:0x%08.8ulx, [1]:0x%08.8ulx, [6]:0x%08.8ulx\n",
+    pMsg, msgOffset, pMsg[1], pMsg[6]);
+#endif /* DEBUG */
+   
+     /* post to Inbound Post Q */   
+    pPab->p_atu->InQueue = msgOffset;
+    
+#ifdef DEBUG
+kprintf("Return status to p32 = 0x%08.8ulx\n", p32);
+#endif /* DEBUG */
+    
+     /* wait for response */
+    timeout = 1000000;
+    while(1)
+    {
+        int i;
+        
+        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
+            ;
+            
+        if (p32[0] && p32[1])
+            break;
+            
+        if (!timeout--)
+        {
+#ifdef DEBUG
+            kprintf("Timeout waiting for status from adapter\n");
+kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
+#endif /* DEBUG */
+            return RC_RTN_NO_STATUS;
+        }
+    }
+            
+#ifdef DEBUG
+kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
+#endif /* DEBUG */
+    /* get adapter state */
+    pPab->ADAPTERState = ((volatile PU8)p32)[10];
+    pPab->InboundMFrameSize  = ((volatile PU16)p32)[6];
+    
+#ifdef DEBUG
+    kprintf("adapter state 0x%02.2x InFrameSize = 0x%04.4x\n", 
+                        pPab->ADAPTERState, pPab->InboundMFrameSize);
+#endif /* DEBUG */
+    return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** SendEnableSysMsg()
+**
+**
+** =========================================================================
+*/
+static int 
+SendEnableSysMsg(PPAB pPab)
+{
+    U32 msgOffset; // timeout;
+    volatile PU32 pMsg;
+
+    msgOffset = pPab->p_atu->InQueue;
+
+    if (msgOffset == 0xFFFFFFFF)
+    {
+#ifdef DEBUG
+        kprintf("SendEnableSysMsg(): Inbound Free Q empty!\n");
+#endif /* DEBUG */
+        return RC_RTN_FREE_Q_EMPTY;
+    }
+
+     /* calc virual address of msg - virual already mapped to physical */
+    pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
+
+#ifdef DEBUG
+kprintf("SendEnableSysMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
+#endif /* DEBUG */
+
+    pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
+    pMsg[1] = RC_CMD_SYS_ENABLE << 24 | HOST_TID << 12 | ADAPTER_TID;
+    pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
+    pMsg[3] = 0x110; /* transaction context */
+    pMsg[4] = 0x50657465; /*  RedCreek Private */
+
+     /* post to Inbound Post Q */
+    pPab->p_atu->InQueue = msgOffset;
+
+    return RC_RTN_NO_ERROR;
+}
+
+
+/*
+** =========================================================================
+** FillI12OMsgFromTCB()
+**
+** inputs   pMsgU32 - virual pointer (mapped to physical) of message frame
+**          pXmitCntrlBlock - pointer to caller buffer control block.
+**
+** fills in LAN SGL after Transaction Control Word or Bucket Count.
+** =========================================================================
+*/
+static int 
+FillAdapterMsgSGLFromTCB(PU32 pMsgFrame, PRCTCB pTransCtrlBlock)
+{
+    unsigned int nmbrBuffers, nmbrSeg, nmbrDwords, context, flags;
+    PU32 pTCB, pMsg;
+
+ /* SGL element flags */   
+#define EOB        0x40000000
+#define LE         0x80000000
+#define SIMPLE_SGL 0x10000000
+#define BC_PRESENT 0x01000000
+
+    pTCB = (PU32)pTransCtrlBlock;
+    pMsg = pMsgFrame;
+    nmbrDwords = 0;
+
+#ifdef DEBUG
+ kprintf("FillAdapterMsgSGLFromTCBX\n");
+kprintf("TCB  0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+               pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
+kprintf("pTCB 0x%08.8ulx, pMsg 0x%08.8ulx\n", pTCB, pMsg);
+#endif /* DEBUG */
+    
+    nmbrBuffers = *pTCB++;
+    
+    if (!nmbrBuffers)
+    {
+        return -1;
+    }
+
+    do
+    {
+        context = *pTCB++; /* buffer tag (context) */
+        nmbrSeg = *pTCB++; /* number of segments */
+
+        if (!nmbrSeg)
+        {
+            return -1;
+        }
+        
+        flags = SIMPLE_SGL | BC_PRESENT;
+
+        if (1 == nmbrSeg)
+        {
+            flags |= EOB;
+        
+            if (1 == nmbrBuffers)
+                flags |= LE;
+        }    
+
+         /* 1st SGL buffer element has context */
+        pMsg[0] = pTCB[0] | flags ; /* send over count (segment size) */
+        pMsg[1] = context;
+        pMsg[2] = pTCB[1]; /* send buffer segment physical address */
+        nmbrDwords += 3;
+        pMsg += 3;
+        pTCB += 2;
+
+        
+        if (--nmbrSeg)
+        {
+            do
+            {
+                flags = SIMPLE_SGL;
+                
+                if (1 == nmbrSeg)
+                {
+                    flags |= EOB;
+                
+                    if (1 == nmbrBuffers)
+                        flags |= LE;
+                }    
+                
+                pMsg[0] = pTCB[0] | flags;  /* send over count */
+                pMsg[1] = pTCB[1];   /* send buffer segment physical address */
+                nmbrDwords += 2;
+                pTCB += 2;
+                pMsg += 2;
+        
+            } while (--nmbrSeg);
+        }
+        
+    } while (--nmbrBuffers);
+    
+    return nmbrDwords;
+}
+
+
+/*
+** =========================================================================
+** ProcessOutboundAdapterMsg()
+**
+** process reply message
+** * change to msg structure *
+** =========================================================================
+*/
+static void 
+ProcessOutboundAdapterMsg(PPAB pPab, U32 phyAddrMsg)
+{
+    PU8 p8Msg;
+    PU32 p32;
+  //  U16 count;
+    
+    
+    p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
+    p32 = (PU32)p8Msg;
+    
+#ifdef DEBUG
+ kprintf("VXD: ProcessOutboundAdapterMsg - pPab 0x%08.8ulx, phyAdr 0x%08.8ulx, linAdr 0x%08.8ulx\n", pPab, phyAddrMsg, p8Msg);
+ kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
+ kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
+#endif /* DEBUG */
+
+    if (p32[4] >> 24 != RC_REPLY_STATUS_SUCCESS)
+    {
+#ifdef DEBUG
+        kprintf("Message reply status not success\n");
+#endif /* DEBUG */
+        return;
+    }
+    
+    switch (p8Msg[7] )  /* function code byte */
+    {
+        case RC_CMD_SYS_TAB_SET:
+            msgFlag = 1;
+#ifdef DEBUG
+        kprintf("Received RC_CMD_SYS_TAB_SET reply\n");
+#endif /* DEBUG */
+            break;
+
+        case RC_CMD_HRT_GET:
+            msgFlag = 1;
+#ifdef DEBUG
+        kprintf("Received RC_CMD_HRT_GET reply\n");
+#endif /* DEBUG */
+            break;
+        
+        case RC_CMD_LCT_NOTIFY:
+            msgFlag = 1;
+#ifdef DEBUG
+        kprintf("Received RC_CMD_LCT_NOTIFY reply\n");
+#endif /* DEBUG */
+            break;
+        
+        case RC_CMD_SYS_ENABLE:
+            msgFlag = 1;
+#ifdef DEBUG
+        kprintf("Received RC_CMD_SYS_ENABLE reply\n");
+#endif /* DEBUG */
+            break;
+
+        default:    
+#ifdef DEBUG
+        kprintf("Received UNKNOWN reply\n");
+#endif /* DEBUG */
+            break;
+    }
+}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/rcmtl.h linux/drivers/net/rcmtl.h
--- v2.1.131/linux/drivers/net/rcmtl.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rcmtl.h	Fri Dec 18 09:39:34 1998
@@ -0,0 +1,580 @@
+/*
+** *************************************************************************
+**
+**
+**     R C M T L . H             $Revision: 3 $
+**
+**
+**  RedCreek Message Transport Layer header file.
+**
+**  ---------------------------------------------------------------------
+**  ---     Copyright (c) 1997-1998, RedCreek Communications Inc.     ---
+**  ---                   All rights reserved.                        ---
+**  ---------------------------------------------------------------------
+**
+**  File Description:
+**
+**  Header file for host message transport layer API and data types.
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation; either version 2 of the License, or
+**  (at your option) any later version.
+
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** *************************************************************************
+*/
+
+#ifndef RCMTL_H
+#define RCMTL_H
+
+/* Linux specific includes */
+#define kprintf printk
+#ifdef RC_LINUX_MODULE     /* linux modules need non-library version of string functions */
+#include <linux/string.h>
+#else
+#include <string.h>
+#endif
+
+/* PCI/45 Configuration space values */
+#define RC_PCI45_VENDOR_ID  0x4916
+#define RC_PCI45_DEVICE_ID  0x1960
+
+
+ /* RedCreek API function return values */
+#define RC_RTN_NO_ERROR             0
+#define RC_RTN_NOT_INIT             1
+#define RC_RTN_FREE_Q_EMPTY         2
+#define RC_RTN_TCB_ERROR            3
+#define RC_RTN_TRANSACTION_ERROR    4
+#define RC_RTN_ADAPTER_ALREADY_INIT 5
+#define RC_RTN_MALLOC_ERROR         6
+#define RC_RTN_ADPTR_NOT_REGISTERED 7
+#define RC_RTN_MSG_REPLY_TIMEOUT    8
+#define RC_RTN_NO_STATUS            9
+#define RC_RTN_NO_FIRM_VER         10
+#define RC_RTN_NO_LINK_SPEED       11
+
+/* Driver capability flags */
+#define WARM_REBOOT_CAPABLE      0x01
+
+ /* scalar data types */
+typedef unsigned char   U8;
+typedef unsigned char*  PU8;
+typedef unsigned short  U16;
+typedef unsigned short* PU16;
+typedef unsigned long   U32;
+typedef unsigned long*  PU32;
+typedef unsigned long   BF;
+typedef int             RC_RETURN;
+
+
+ /* 
+ ** type PFNWAITCALLBACK
+ **
+ ** pointer to void function - type used for WaitCallback in some functions 
+ */
+typedef void (*PFNWAITCALLBACK)(void);  /* void argument avoids compiler complaint */
+
+ /*
+ ** type PFNTXCALLBACK 
+ **
+ ** Pointer to user's transmit callback function.  This user function is
+ ** called from RCProcMsgQ() when packet have been transmitted from buffers
+ ** given in the RCSendPacket() function.  BufferContext is a pointer to
+ ** an array of 32 bit context values.  These are the values the user assigned
+ ** and passed in the TCB to the RCSendPacket() function.  PcktCount
+ ** indicates the number of buffer context values in the BufferContext[] array.
+ ** The User's TransmitCallbackFunction should recover (put back in free queue)
+ ** the packet buffers associated with the buffer context values.
+ */
+typedef void (*PFNTXCALLBACK)(U32  Status,
+                              U16  PcktCount,
+                              PU32 BufferContext,
+                              U16  AdaterID);
+
+ /* 
+ ** type PFNRXCALLBACK 
+ **
+ ** Pointer to user's receive callback function.  This user function
+ ** is called from RCProcMsgQ() when packets have been received into
+ ** previously posted packet buffers throught the RCPostRecvBuffers() function.
+ ** The received callback function should process the Packet Descriptor Block
+ ** pointed to by PacketDescBlock. See Packet Decription Block below.
+ */
+typedef void (*PFNRXCALLBACK)(U32  Status,
+                              U8   PktCount,
+                              U32  BucketsRemain,
+                              PU32 PacketDescBlock,
+                              U16  AdapterID);
+
+ /* 
+ ** type PFNCALLBACK 
+ **
+ ** Pointer to user's generic callback function.  This user function
+ ** can be passed to LANReset or LANShutdown and is called when the 
+ ** the reset or shutdown is complete.
+ ** Param1 and Param2 are invalid for LANReset and LANShutdown.
+ */
+typedef void (*PFNCALLBACK)(U32  Status,
+                              U32  Param1,
+                              U32  Param2,
+                              U16  AdapterID);
+
+/*
+** Status - Transmit and Receive callback status word 
+**
+** A 32 bit Status is returned to the TX and RX callback functions.  This value
+** contains both the reply status and the detailed status as follows:
+**
+**  32    24     16            0
+**  +------+------+------------+
+**  | Reply|      |  Detailed  |
+**  |Status|   0  |   Status   |
+**  +------+------+------------+
+**
+** Reply Status and Detailed Status of zero indicates No Errors.
+*/
+ /* reply message status defines */
+#define    RC_REPLY_STATUS_SUCCESS                    0x00
+#define    RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER     0x02
+#define    RC_REPLY_STATUS_TRANSACTION_ERROR          0x0A
+
+
+/* DetailedStatusCode defines */
+#define    RC_DSC_SUCCESS                         0x0000
+#define    RC_DSC_DEVICE_FAILURE                  0x0001
+#define    RC_DSC_DESTINATION_NOT_FOUND           0x0002
+#define    RC_DSC_TRANSMIT_ERROR                  0x0003
+#define    RC_DSC_TRANSMIT_ABORTED                0x0004
+#define    RC_DSC_RECEIVE_ERROR                   0x0005
+#define    RC_DSC_RECEIVE_ABORTED                 0x0006
+#define    RC_DSC_DMA_ERROR                       0x0007
+#define    RC_DSC_BAD_PACKET_DETECTED             0x0008
+#define    RC_DSC_OUT_OF_MEMORY                   0x0009
+#define    RC_DSC_BUCKET_OVERRUN                  0x000A
+#define    RC_DSC_IOP_INTERNAL_ERROR              0x000B
+#define    RC_DSC_CANCELED                        0x000C
+#define    RC_DSC_INVALID_TRANSACTION_CONTEXT     0x000D
+#define    RC_DSC_DESTINATION_ADDRESS_DETECTED    0x000E
+#define    RC_DSC_DESTINATION_ADDRESS_OMITTED     0x000F
+#define    RC_DSC_PARTIAL_PACKET_RETURNED         0x0010
+
+
+/*
+** Packet Description Block   (Received packets)
+**
+** A pointer to this block structure is returned to the ReceiveCallback 
+** function.  It contains the list of packet buffers which have either been
+** filled with a packet or returned to host due to a LANReset function. 
+** Currently there will only be one packet per receive bucket (buffer) posted. 
+**
+**   32   24               0     
+**  +-----------------------+  -\
+**  |   Buffer 1 Context    |    \
+**  +-----------------------+     \
+**  |      0xC0000000       |     / First Bucket Descriptor
+**  +-----+-----------------+    /
+**  |  0  | packet 1 length |   / 
+**  +-----------------------+  -\
+**  |   Buffer 2 Context    |    \
+**  +-----------------------+     \
+**  |      0xC0000000       |     / Second Bucket Descriptor
+**  +-----+-----------------+    /
+**  |  0  | packet 2 length |   / 
+**  +-----+-----------------+  -
+**  |         ...           |  ----- more bucket descriptors
+**  +-----------------------+  -\
+**  |   Buffer n Context    |    \
+**  +-----------------------+     \
+**  |      0xC0000000       |     / Last Bucket Descriptor
+**  +-----+-----------------+    /
+**  |  0  | packet n length |   / 
+**  +-----+-----------------+  -
+**
+** Buffer Context values are those given to adapter in the TCB on calls to
+** RCPostRecvBuffers().
+**  
+*/
+
+
+
+/*
+** Transaction Control Block (TCB) structure
+**
+** A structure like this is filled in by the user and passed by reference to 
+** RCSendPacket() and RCPostRecvBuffers() functions.  Minimum size is five
+** 32-bit words for one buffer with one segment descriptor.  
+** MAX_NMBR_POST_BUFFERS_PER_MSG defines the maximum single segment buffers
+** that can be described in a given TCB.
+**
+**   32                    0
+**  +-----------------------+
+**  |   Buffer Count        |  Number of buffers in the TCB
+**  +-----------------------+
+**  |   Buffer 1 Context    |  first buffer reference
+**  +-----------------------+
+**  |   Buffer 1 Seg Count  |  number of segments in buffer
+**  +-----------------------+
+**  |   Buffer 1 Seg Desc 1 |  first segment descriptor (size, physical address)
+**  +-----------------------+
+**  |         ...           |  more segment descriptors (size, physical address)
+**  +-----------------------+
+**  |   Buffer 1 Seg Desc n |  last segment descriptor (size, physical address)
+**  +-----------------------+
+**  |   Buffer 2 Context    |  second buffer reference
+**  +-----------------------+
+**  |   Buffer 2 Seg Count  |  number of segments in buffer
+**  +-----------------------+
+**  |   Buffer 2 Seg Desc 1 |  segment descriptor (size, physical address)
+**  +-----------------------+
+**  |         ...           |  more segment descriptors (size, physical address)
+**  +-----------------------+
+**  |   Buffer 2 Seg Desc n |
+**  +-----------------------+
+**  |         ...           |  more buffer descriptor blocks ...
+**  +-----------------------+
+**  |   Buffer n Context    |
+**  +-----------------------+
+**  |   Buffer n Seg Count  |
+**  +-----------------------+
+**  |   Buffer n Seg Desc 1 |
+**  +-----------------------+
+**  |         ...           |
+**  +-----------------------+
+**  |   Buffer n Seg Desc n |
+**  +-----------------------+
+**
+**
+** A TCB for one contigous packet buffer would look like the following:
+**
+**   32                    0
+**  +-----------------------+
+**  |         1             |  one buffer in the TCB
+**  +-----------------------+
+**  |  <user's Context>     |  user's buffer reference
+**  +-----------------------+
+**  |         1             |  one segment buffer
+**  +-----------------------+                            _
+**  |    <buffer size>      |  size                       \ 
+**  +-----------------------+                              \ segment descriptor
+**  |  <physical address>   |  physical address of buffer  /
+**  +-----------------------+                            _/
+**
+*/
+
+ /* Buffer Segment Descriptor */
+typedef struct
+{
+    U32 size;
+    U32 phyAddress;
+}
+ BSD, *PBSD;
+ 
+typedef PU32 PRCTCB;
+/*
+** -------------------------------------------------------------------------
+** Exported functions comprising the API to the message transport layer
+** -------------------------------------------------------------------------
+*/
+
+
+ /*
+ ** InitRCApiMsgLayer()
+ ** 
+ ** Called once prior to using the API message transport layer.  User 
+ ** provides both the physical and virual address of a locked page buffer 
+ ** that is used as a private buffer for the RedCreek API message
+ ** transport layer.  This buffer must be a contigous memory block of a 
+ ** minimum of 16K bytes and long word aligned.  The user also must provide
+ ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
+ ** system.  The user provided value AdapterID is a zero based index of the
+ ** Ravlin 45/PCI adapter.  This interface number is used in all subsequent API
+ ** calls to identify which adpapter for which the function is intended.  
+ ** Up to sixteen interfaces are supported with this API.
+ **
+ ** Inputs:  AdapterID - interface number from 0 to 15
+ **          pciBaseAddr - virual base address of PCI (set by BIOS)
+ **          p_msgbuf - virual address to private message block (min. 16K)
+ **          p_phymsgbuf - physical address of private message block
+ **          TransmitCallbackFunction - address of user's TX callback function
+ **          ReceiveCallbackFunction  - address of user's RX callback function
+ **
+ */
+RC_RETURN InitRCApiMsgLayer(U16 AdapterID, U32 pciBaseAddr, 
+                            PU8 p_msgbuf,  PU8 p_phymsgbuf,
+                            PFNTXCALLBACK TransmitCallbackFunction,
+                            PFNRXCALLBACK ReceiveCallbackFunction,
+                            PFNCALLBACK   RebootCallbackFunction);
+
+ /*
+ ** RCSetRavlinIPandMask()
+ **
+ ** Set the Ravlin 45/PCI cards IP address and network mask.
+ **
+ ** IP address and mask must be in network byte order.
+ ** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
+ ** 0x04030201 and 0x00FFFFFF on a little endian machine.
+ **
+ */
+RC_RETURN RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask);
+
+
+/*
+** =========================================================================
+** RCGetRavlinIPandMask()
+**
+** get the IP address and MASK from the card
+** 
+** =========================================================================
+*/
+RC_RETURN
+RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask, 
+                        PFNWAITCALLBACK WaitCallback);
+
+ /* 
+ ** RCProcMsgQ()
+ ** 
+ ** Called from user's polling loop or Interrupt Service Routine for a PCI 
+ ** interrupt from the RedCreek PCI adapter.  User responsible for determining
+ ** and hooking the PCI interrupt. This function will call the registered
+ ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
+ ** if a TX or RX transaction has completed.
+ */
+void RCProcMsgQ(U16 AdapterID);
+
+
+ /*
+ ** Disable and Enable Adapter interrupts.  Adapter interrupts are enabled at 
+ ** Init time but can be disabled and re-enabled through these two function calls.
+ ** Packets will still be put into any posted recieved buffers and packets will
+ ** be sent through RCSendPacket() functions.  Disabling Adapter interrupts
+ ** will prevent hardware interrupt to host even though the outbound msg
+ ** queue is not emtpy.
+ */
+RC_RETURN RCEnableAdapterInterrupts(U16 adapterID);
+RC_RETURN RCDisableAdapterInterrupts(U16 AdapterID);
+
+
+ /* 
+ ** RCPostRecvBuffers()
+ ** 
+ ** Post user's page locked buffers for use by the PCI adapter to
+ ** return ethernet packets received from the LAN.  Transaction Control Block,
+ ** provided by user, contains buffer descriptor(s) which includes a buffer
+ ** context number along with buffer size and physical address.  See TCB above.
+ ** The buffer context and actual packet length are returned to the 
+ ** ReceiveCallbackFunction when packets have been received.  Buffers posted
+ ** to the RedCreek adapter are considered owned by the adapter until the
+ ** context is return to user through the ReceiveCallbackFunction.
+ */
+RC_RETURN RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransactionCtrlBlock);
+#define MAX_NMBR_POST_BUFFERS_PER_MSG 32
+
+ /*
+ ** RCSendPacket()
+ ** 
+ ** Send user's ethernet packet from a locked page buffer.  
+ ** Packet must have full MAC header, however without a CRC.  
+ ** Initiator context is a user provided value that is returned 
+ ** to the TransmitCallbackFunction when packet buffer is free.
+ ** Transmit buffer are considered owned by the adapter until context's
+ ** returned to user through the TransmitCallbackFunction.
+ */
+RC_RETURN RCSendPacket(U16 AdapterID, 
+                          U32 context, 
+                          PRCTCB pTransactionCtrlBlock);
+
+
+ /* Ethernet Link Statistics structure */
+typedef struct tag_RC_link_stats
+{
+    U32 TX_good;      /* good transmit frames */
+    U32 TX_maxcol;    /* frames not TX due to MAX collisions */
+    U32 TX_latecol;   /* frames not TX due to late collisions */
+    U32 TX_urun;      /* frames not TX due to DMA underrun */
+    U32 TX_crs;       /* frames TX with lost carrier sense */
+    U32 TX_def;       /* frames deferred due to activity on link */
+    U32 TX_singlecol; /* frames TX with one and only on collision */
+    U32 TX_multcol;   /* frames TX with more than one collision */
+    U32 TX_totcol;    /* total collisions detected during TX */
+    U32 Rcv_good;     /* good frames received */
+    U32 Rcv_CRCerr;   /* frames RX and discarded with CRC errors */
+    U32 Rcv_alignerr; /* frames RX with alignment and CRC errors */
+    U32 Rcv_reserr;   /* good frames discarded due to no RX buffer */
+    U32 Rcv_orun;     /* RX frames lost due to FIFO overrun */
+    U32 Rcv_cdt;      /* RX frames with collision during RX */
+    U32 Rcv_runt;     /* RX frames shorter than 64 bytes */
+}
+ RCLINKSTATS, *P_RCLINKSTATS;
+
+ /*
+ ** RCGetLinkStatistics()
+ **
+ ** Returns link statistics in user's structure at address StatsReturnAddr
+ ** If given, not NULL, the function WaitCallback is called during the wait
+ ** loop while waiting for the adapter to respond.
+ */
+RC_RETURN RCGetLinkStatistics(U16 AdapterID,
+                              P_RCLINKSTATS StatsReturnAddr,
+                              PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCGetLinkStatus()
+ **
+ ** Return link status, up or down, to user's location addressed by ReturnAddr.
+ ** If given, not NULL, the function WaitCallback is called during the wait
+ ** loop while waiting for the adapter to respond.
+ */
+RC_RETURN RCGetLinkStatus(U16 AdapterID, 
+                          PU32 pReturnStatus,
+                          PFNWAITCALLBACK WaitCallback);
+                               
+ /* Link Status defines - value returned in pReturnStatus */
+#define LAN_LINK_STATUS_DOWN     0
+#define LAN_LINK_STATUS_UP       1
+
+ /*
+ ** RCGetMAC()
+ **
+ ** Get the current MAC address assigned to user.  RedCreek Ravlin 45/PCI 
+ ** has two MAC addresses.  One which is private to the PCI Card, and 
+ ** another MAC which is given to the user as its link layer MAC address. The
+ ** adapter runs in promiscous mode because of the dual address requirement.
+ ** The MAC address is returned to the unsigned char array pointer to by mac.
+ */
+RC_RETURN RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback);
+
+ /*
+ ** RCSetMAC()
+ **
+ ** Set a new user port MAC address.  This address will be returned on
+ ** subsequent RCGetMAC() calls.
+ */
+RC_RETURN RCSetMAC(U16 AdapterID, PU8 mac);
+
+ /*
+ ** RCSetLinkSpeed()
+ **
+ ** set adapter's link speed based on given input code.
+ */
+RC_RETURN RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode);
+ /* Set link speed codes */
+#define LNK_SPD_AUTO_NEG_NWAY   0
+#define LNK_SPD_100MB_FULL      1
+#define LNK_SPD_100MB_HALF      2
+#define LNK_SPD_10MB_FULL       3
+#define LNK_SPD_10MB_HALF       4
+
+
+
+
+ /*
+ ** RCGetLinkSpeed()
+ **
+ ** Return link speed code.
+ */
+ /* Return link speed codes */
+#define LNK_SPD_UNKNOWN         0
+#define LNK_SPD_100MB_FULL      1
+#define LNK_SPD_100MB_HALF      2
+#define LNK_SPD_10MB_FULL       3
+#define LNK_SPD_10MB_HALF       4
+
+RC_RETURN
+RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
+
+/*
+** =========================================================================
+** RCReportDriverCapability(U16 AdapterID, U32 capability)
+**
+** Currently defined bits:
+** WARM_REBOOT_CAPABLE   0x01
+**
+** =========================================================================
+*/
+RC_RETURN
+RCReportDriverCapability(U16 AdapterID, U32 capability);
+
+/*
+** RCGetFirmwareVer()
+**
+** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
+**
+** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
+*/
+RC_RETURN
+RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
+
+/*
+** ----------------------------------------------
+** LAN adapter Reset and Shutdown functions
+** ----------------------------------------------
+*/
+ /* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */
+#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS  0x0001 
+#define RC_RESOURCE_RETURN_PEND_TX_BUFFERS    0x0002
+
+ /*
+ ** RCResetLANCard()
+ **
+ ** Reset LAN card operation.  Causes a software reset of the ethernet
+ ** controller and restarts the command and receive units. Depending on 
+ ** the ResourceFlags given, the buffers are either returned to the
+ ** host with reply status of RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
+ ** detailed status of RC_DSC_CANCELED (new receive buffers must be
+ ** posted after issuing this) OR the buffers are kept and reused by
+ ** the ethernet controller. If CallbackFunction is not NULL, the function
+ ** will be called when the reset is complete.  If the CallbackFunction is
+ ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset 
+ ** to complete (please disable adapter interrupts during this method).
+ ** Any outstanding transmit or receive buffers that are complete will be
+ ** returned via the normal reply messages before the requested resource
+ ** buffers are returned.
+ ** A call to RCPostRecvBuffers() is needed to return the ethernet to full
+ ** operation if the receive buffers were returned during LANReset.
+ ** Note: The IOP status is not affected by a LAN reset.
+ */
+RC_RETURN RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+
+ /*
+ ** RCShutdownLANCard()
+ **
+ ** Shutdown LAN card operation and put into an idle (suspended) state.
+ ** The LAN card is restarted with RCResetLANCard() function.
+ ** Depending on the ResourceFlags given, the buffers are either returned 
+ ** to the host with reply status of RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 
+ ** and detailed status of RC_DSC_CANCELED (new receive buffers must be
+ ** posted after issuing this) OR the buffers are kept and reused by
+ ** the ethernet controller. If CallbackFunction is not NULL, the function
+ ** will be called when the reset is complete.  If the CallbackFunction is
+ ** NULL,a 1 will be put into the ReturnAddr after waiting for the reset 
+ ** to complete (please disable adapter interrupts during this method).
+ ** Any outstanding transmit or receive buffers that are complete will be
+ ** returned via the normal reply messages before the requested resource
+ ** buffers are returned.
+ ** Note: The IOP status is not affected by a LAN shutdown.
+ */                                      
+RC_RETURN 
+RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+
+ /*
+ ** RCResetAdapter();
+ **     Initializes ADAPTERState to ADAPTER_STATE_RESET.
+ **     Stops access to outbound message Q.
+ **     Discards any outstanding transmit or posted receive buffers.
+ **     Clears outbound message Q. 
+ */
+RC_RETURN 
+RCResetAdapter(U16 AdapterID);
+
+#endif /* RCMTL_H */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- v2.1.131/linux/drivers/net/rcpci45.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/rcpci45.c	Fri Dec 18 09:39:34 1998
@@ -0,0 +1,1323 @@
+/* 
+**  RCpci45.c  
+**
+**
+**
+**  ---------------------------------------------------------------------
+**  ---     Copyright (c) 1998, RedCreek Communications Inc.          ---
+**  ---                   All rights reserved.                        ---
+**  ---------------------------------------------------------------------
+**
+** Written by Pete Popov and Brian Moyle.
+**
+** Known Problems
+** 
+** Billions and Billions...  
+**
+** ... apparently added by Brian.  Pete knows of no bugs.
+**
+**  TODO:
+**      -Get rid of the wait loops in the API and replace them
+**       with system independent delays ...something like
+**       "delayms(2)".
+**
+**  This program is free software; you can redistribute it and/or modify
+**  it under the terms of the GNU General Public License as published by
+**  the Free Software Foundation; either version 2 of the License, or
+**  (at your option) any later version.
+
+**  This program is distributed in the hope that it will be useful,
+**  but WITHOUT ANY WARRANTY; without even the implied warranty of
+**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+**  GNU General Public License for more details.
+
+**  You should have received a copy of the GNU General Public License
+**  along with this program; if not, write to the Free Software
+**  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+**
+**  Ported to 2.1.x by Alan Cox 1998/12/9. If this doesnt work try 2.0.x
+**  and let me know.
+**
+***************************************************************************/
+
+static char *version =
+"RedCreek Communications PCI linux driver version 1.32 Beta\n";
+
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/malloc.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/bios32.h>
+#include <linux/timer.h>
+#include <asm/irq.h>            /* For NR_IRQS only. */
+#include <asm/bitops.h>
+#include <asm/io.h>
+
+#include <asm/uaccess.h>
+
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#define RC_LINUX_MODULE
+#include "rcmtl.h"
+#include "rcif.h"
+
+#define RUN_AT(x) (jiffies + (x))
+#define DEV_ALLOC_SKB(len) dev_alloc_skb(len + 2)
+
+#define FREE_IRQ(irqnum, dev) free_irq(irqnum)
+#define REQUEST_IRQ(i,h,f,n, instance) request_irq(i,h,f,n)
+#define IRQ(irq, dev_id, pt_regs) (irq, pt_regs)
+
+#define NEW_MULTICAST
+#include <linux/delay.h>
+
+/* PCI/45 Configuration space values */
+#define RC_PCI45_VENDOR_ID  0x4916
+#define RC_PCI45_DEVICE_ID  0x1960
+
+#define MAX_ETHER_SIZE        1520  
+#define MAX_NMBR_RCV_BUFFERS    96
+#define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16
+#define BD_SIZE 3           /* Bucket Descriptor size */
+#define BD_LEN_OFFSET 2     /* Bucket Descriptor offset to length field */
+
+
+/* RedCreek LAN device Target ID */
+#define RC_LAN_TARGET_ID  0x10 
+/* RedCreek's OSM default LAN receive Initiator */
+#define DEFAULT_RECV_INIT_CONTEXT  0xA17  
+
+
+static U32 DriverControlWord =  0;
+
+static void rc_timer(unsigned long);
+
+/*
+ * Driver Private Area, DPA.
+ */
+typedef struct
+{
+
+     /* 
+      *    pointer to the device structure which is part
+      * of the interface to the Linux kernel.
+      */
+      struct device *dev;            
+     
+     char devname[8];                /* "ethN" string */
+     U8     id;                        /* the AdapterID */
+     U32    pci_addr;               /* the pci address of the adapter */
+     U32    bus;
+     U32    function;
+     struct timer_list timer;        /*  timer */
+     struct enet_statistics  stats; /* the statistics structure */
+     struct device *next;            /* points to the next RC adapter */
+     unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
+     unsigned char shutdown;
+     unsigned char reboot;
+     unsigned char nexus;
+     PU8    PLanApiPA;             /* Pointer to Lan Api Private Area */
+
+}
+DPA, *PDPA;
+
+#define MAX_ADAPTERS 32
+
+static PDPA  PCIAdapters[MAX_ADAPTERS] = 
+{
+     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+
+
+static int RCscan(void);
+static struct device 
+*RCfound_device(struct device *, int, int, int, int, int, int);
+
+static int RCprobe1(struct device *);
+static int RCopen(struct device *);
+static int RC_xmit_packet(struct sk_buff *, struct device *);
+static void RCinterrupt(int, void *, struct pt_regs *);
+static int RCclose(struct device *dev);
+static struct enet_statistics *RCget_stats(struct device *);
+static int RCioctl(struct device *, struct ifreq *, int);
+static int RCconfig(struct device *, struct ifmap *);
+static void RCxmit_callback(U32, U16, PU32, U16);
+static void RCrecv_callback(U32, U8, U32, PU32, U16);
+static void RCreset_callback(U32, U32, U32, U16);
+static void RCreboot_callback(U32, U32, U32, U16);
+static int RC_allocate_and_post_buffers(struct device *, int);
+
+
+/* A list of all installed RC devices, for removing the driver module. */
+static struct device *root_RCdev = NULL;
+
+#ifdef MODULE
+int init_module(void)
+#else
+int rcpci_probe(struct netdevice *dev)
+#endif
+{
+     int cards_found;
+
+     printk(version);
+
+     root_RCdev = NULL;
+     cards_found = RCscan();
+#ifdef MODULE     
+     return cards_found ? 0 : -ENODEV;
+#else
+     return -1;
+#endif          
+}
+
+static int RCscan(void)
+{
+     int cards_found = 0;
+     struct device *dev = 0;
+
+     if (pcibios_present()) 
+     {
+          static int pci_index = 0;
+          unsigned char pci_bus, pci_device_fn;
+          int scan_status;
+          int board_index = 0;
+
+          for (;pci_index < 0xff; pci_index++) 
+          {
+               unsigned char pci_irq_line;
+               unsigned short pci_command, vendor, device, class;
+               unsigned int pci_ioaddr;
+
+
+               scan_status =  
+                    (pcibios_find_device (RC_PCI45_VENDOR_ID, 
+                                          RC_PCI45_DEVICE_ID, 
+                                          pci_index, 
+                                          &pci_bus, 
+                                          &pci_device_fn));
+#ifdef RCDEBUG
+               printk("rc scan_status = 0x%X\n", scan_status);
+#endif
+               if (scan_status != PCIBIOS_SUCCESSFUL)
+                    break;
+               pcibios_read_config_word(pci_bus, 
+                                        pci_device_fn, 
+                                        PCI_VENDOR_ID, &vendor);
+               pcibios_read_config_word(pci_bus, 
+                                        pci_device_fn,
+                                        PCI_DEVICE_ID, &device);
+               pcibios_read_config_byte(pci_bus, 
+                                        pci_device_fn,
+                                        PCI_INTERRUPT_LINE, &pci_irq_line);
+               pcibios_read_config_dword(pci_bus, 
+                                         pci_device_fn,
+                                         PCI_BASE_ADDRESS_0, &pci_ioaddr);
+               pcibios_read_config_word(pci_bus, 
+                                        pci_device_fn,
+                                        PCI_CLASS_DEVICE, &class);
+
+               pci_ioaddr &= ~0xf;
+
+#ifdef RCDEBUG
+               printk("rc: Found RedCreek PCI adapter\n");
+               printk("rc: pci class = 0x%x  0x%x \n", class, class>>8);
+               printk("rc: pci_bus = %d,  pci_device_fn = %d\n", pci_bus, pci_device_fn);
+               printk("rc: pci_irq_line = 0x%x \n", pci_irq_line);
+               printk("rc: pci_ioaddr = 0x%x\n", pci_ioaddr);
+#endif
+
+#if 0
+               if (check_region(pci_ioaddr, 32768))
+               {
+                    printk("rc: check_region failed\n");
+                    continue;
+               }
+               else
+               {
+                    printk("rc: check_region passed\n");
+               }
+#endif
+               
+                /*
+                 * Get and check the bus-master and latency values.
+                 * Some PCI BIOSes fail to set the master-enable bit.
+                 */
+
+                pcibios_read_config_word(pci_bus, 
+                                         pci_device_fn,
+                                         PCI_COMMAND, 
+                                         &pci_command);
+                if ( ! (pci_command & PCI_COMMAND_MASTER)) {
+                     printk("rc: PCI Master Bit has not been set!\n");
+                            
+                     pci_command |= PCI_COMMAND_MASTER;
+                     pcibios_write_config_word(pci_bus, 
+                                               pci_device_fn,
+                                               PCI_COMMAND, 
+                                               pci_command);
+                }
+                if ( ! (pci_command & PCI_COMMAND_MEMORY)) {
+                /*
+                 * If the BIOS did not set the memory enable bit, what else
+                 * did it not initialize?  Skip this adapter.
+                 */
+                     printk("rc: Adapter %d, PCI Memory Bit has not been set!\n",
+                         cards_found);
+                     printk("rc: Bios problem? \n");
+                     continue;
+                }
+                    
+               dev = RCfound_device(dev, pci_ioaddr, pci_irq_line,
+                                    pci_bus, pci_device_fn,
+                                    board_index++, cards_found);
+
+               if (dev) {
+                    dev = 0;
+                    cards_found++;
+               }
+          }
+     }
+     printk("rc: found %d cards \n", cards_found);
+     return cards_found;
+}
+
+static struct device *
+RCfound_device(struct device *dev, int memaddr, int irq, 
+               int bus, int function, int product_index, int card_idx)
+{
+     int dev_size = 32768;        
+     unsigned long *vaddr=0;
+     PDPA pDpa;
+     int init_status;
+
+     /* 
+      * Allocate and fill new device structure. 
+      * We need enough for struct device plus DPA plus the LAN API private
+      * area, which requires a minimum of 16KB.  The top of the allocated
+      * area will be assigned to struct device; the next chunk will be
+      * assigned to DPA; and finally, the rest will be assigned to the
+      * the LAN API layer.
+      */
+     dev = (struct device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
+     memset(dev, 0, dev_size);
+#ifdef RCDEBUG
+     printk("rc: dev = 0x%08X\n", (uint)dev);
+#endif 
+
+     /*
+      * dev->priv will point to the start of DPA.
+      */
+     dev->priv = (void *)(((long)dev + sizeof(struct device) + 15) & ~15);
+     pDpa = dev->priv;
+     dev->name = pDpa->devname;
+
+     pDpa->dev = dev;            /* this is just for easy reference */
+     pDpa->function = function;
+     pDpa->bus = bus;
+     pDpa->id = card_idx;        /* the device number */
+     pDpa->pci_addr = memaddr;
+     PCIAdapters[card_idx] = pDpa;
+#ifdef RCDEBUG
+     printk("rc: pDpa = 0x%x, id = %d \n", (uint)pDpa, (uint)pDpa->id);
+#endif
+
+     /*
+      * Save the starting address of the LAN API private area.  We'll
+      * pass that to InitRCApiMsgLayer().
+      */
+     pDpa->PLanApiPA = (void *)(((long)pDpa + sizeof(DPA) + 0xff) & ~0xff);
+#ifdef RCDEBUG
+     printk("rc: pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
+#endif
+    
+     /* The adapter is accessable through memory-access read/write, not
+      * I/O read/write.  Thus, we need to map it to some virtual address
+      * area in order to access the registers are normal memory.
+      */
+     vaddr = (ulong *) ioremap(memaddr, 32768);
+#ifdef RCDEBUG
+     printk("rc: RCfound_device: 0x%x, priv = 0x%x, vaddr = 0x%x\n", 
+            (uint)dev, (uint)dev->priv, (uint)vaddr);
+#endif
+     dev->base_addr = (unsigned long)vaddr;
+     dev->irq = irq;
+     dev->interrupt = 0;
+
+     /*
+      * Request a shared interrupt line.
+      */
+     if ( request_irq(dev->irq, (void *)RCinterrupt,
+                      SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )
+     {
+          printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );
+          iounmap(vaddr);
+          kfree(dev);
+           return 0;
+     }
+
+     init_status = InitRCApiMsgLayer(pDpa->id, dev->base_addr, 
+                                     pDpa->PLanApiPA, pDpa->PLanApiPA,
+                                     (PFNTXCALLBACK)RCxmit_callback,
+                                     (PFNRXCALLBACK)RCrecv_callback,
+                                     (PFNCALLBACK)RCreboot_callback);
+#ifdef RCDEBUG
+     printk("rc: msg initted: status = 0x%x\n", init_status);
+#endif
+     if (init_status)
+     {
+          printk("rc: Unable to initialize msg layer\n");
+          free_irq(dev->irq, dev);
+          vfree(vaddr);
+          kfree(dev);
+          return 0;
+     }
+     if (RCGetMAC(pDpa->id, dev->dev_addr, NULL))
+     {
+          printk("rc: Unable to get adapter MAC\n");
+          free_irq(dev->irq, dev);
+          vfree(vaddr);
+          kfree(dev);
+          return 0;
+     }
+
+     DriverControlWord |= WARM_REBOOT_CAPABLE;
+     RCReportDriverCapability(pDpa->id, DriverControlWord);
+
+     dev->init = RCprobe1;
+     ether_setup(dev);            /* linux kernel interface */
+
+     pDpa->next = root_RCdev;
+     root_RCdev = dev;
+
+     if (register_netdev(dev) != 0) /* linux kernel interface */
+     {
+          printk("rc: unable to register device \n");
+          free_irq(dev->irq, dev);
+          vfree(vaddr);
+          kfree(dev);
+          return 0;
+     }
+     return dev;
+}
+
+static int RCprobe1(struct device *dev)
+{
+     dev->open = RCopen;
+     dev->hard_start_xmit = RC_xmit_packet;
+     dev->stop = RCclose;
+     dev->get_stats = RCget_stats;
+     dev->do_ioctl = RCioctl;
+     dev->set_config = RCconfig;
+     return 0;
+}
+
+static int
+RCopen(struct device *dev)
+{
+    int post_buffers = MAX_NMBR_RCV_BUFFERS;
+    PDPA pDpa = (PDPA) dev->priv;
+    int count = 0;
+    int requested = 0;
+
+#ifdef RCDEBUG
+    printk("rc: RCopen\n");
+#endif
+    RCEnableAdapterInterrupts(pDpa->id);
+
+    if (pDpa->nexus)
+    {
+       /* This is not the first time RCopen is called.  Thus,
+        * the interface was previously opened and later closed
+        * by RCclose().  RCclose() does a Shutdown; to wake up
+        * the adapter, a reset is mandatory before we can post
+        * receive buffers.  However, if the adapter initiated 
+        * a reboot while the interface was closed -- and interrupts
+        * were turned off -- we need will need to reinitialize
+        * the adapter, rather than simply waking it up.  
+        */
+        printk("rc: Waking up adapter...\n");
+        RCResetLANCard(pDpa->id,0,0,0);
+    }
+    else
+    {
+       pDpa->nexus = 1;
+    }
+
+    while(post_buffers)
+    {
+        if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+            requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
+        else
+            requested = post_buffers;
+        count = RC_allocate_and_post_buffers(dev, requested);
+
+        if ( count < requested )
+        {
+             /*
+              * Check to see if we were able to post any buffers at all.
+              */
+             if (post_buffers == MAX_NMBR_RCV_BUFFERS)
+             {
+                  printk("rc: Error RCopen: not able to allocate any buffers\r\n");
+                  return(-ENOMEM);                    
+             }
+             printk("rc: Warning RCopen: not able to allocate all requested buffers\r\n");
+             break;            /* we'll try to post more buffers later */
+        }
+        else
+             post_buffers -= count;
+    }
+    pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
+    pDpa->shutdown = 0;        /* just in case */
+#ifdef RCDEBUG
+    printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
+#endif
+    MOD_INC_USE_COUNT;
+    return 0;
+}
+
+static int
+RC_xmit_packet(struct sk_buff *skb, struct device *dev)
+{
+
+     PDPA pDpa = (PDPA) dev->priv;
+     singleTCB tcb;
+     psingleTCB ptcb = &tcb;
+     RC_RETURN status = 0;
+    
+     if (dev->tbusy || pDpa->shutdown || pDpa->reboot)
+     {
+#ifdef RCDEBUG
+          printk("rc: RC_xmit_packet: tbusy!\n");
+#endif
+          return 1;
+     }
+      
+     if ( skb->len <= 0 ) 
+     {
+          printk("RC_xmit_packet: skb->len less than 0!\n");
+          return 0;
+     }
+
+     /*
+      * The user is free to reuse the TCB after RCSendPacket() returns, since
+      * the function copies the necessary info into its own private space.  Thus,
+      * our TCB can be a local structure.  The skb, on the other hand, will be
+      * freed up in our interrupt handler.
+      */
+     ptcb->bcount = 1;
+     /* 
+      * we'll get the context when the adapter interrupts us to tell us that
+      * the transmision is done. At that time, we can free skb.
+      */
+     ptcb->b.context = (U32)skb;    
+     ptcb->b.scount = 1;
+     ptcb->b.size = skb->len;
+     ptcb->b.addr = (U32)skb->data;
+
+#ifdef RCDEBUG
+     printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", 
+            (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
+#endif
+     if ( (status = RCSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb))
+          != RC_RTN_NO_ERROR)
+     {
+#ifdef RCDEBUG
+          printk("rc: RC send error 0x%x\n", (uint)status);
+#endif
+          dev->tbusy = 1;
+     }
+     else
+     {
+          dev->trans_start = jiffies;
+          //       dev->tbusy = 0;
+     }
+     /*
+      * That's it!
+      */
+     return 0;
+}
+
+/*
+ * RCxmit_callback()
+ *
+ * The transmit callback routine. It's called by RCProcMsgQ()
+ * because the adapter is done with one or more transmit buffers and
+ * it's returning them to us, or we asked the adapter to return the
+ * outstanding transmit buffers by calling RCResetLANCard() with 
+ * RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag. 
+ * All we need to do is free the buffers.
+ */
+static void 
+RCxmit_callback(U32 Status, 
+                U16 PcktCount, 
+                PU32 BufferContext, 
+                U16 AdapterID)
+{
+    struct sk_buff *skb;
+    PDPA pDpa;
+    struct device *dev;
+
+    pDpa = PCIAdapters[AdapterID];
+    if (!pDpa)
+    {
+        printk("rc: Fatal error: xmit callback, !pDpa\n");
+        return;
+    }
+    dev = pDpa->dev;
+
+        // printk("xmit_callback: Status = 0x%x\n", (uint)Status);
+    if (Status != RC_REPLY_STATUS_SUCCESS)
+    {
+        printk("rc: xmit_callback: Status = 0x%x\n", (uint)Status);
+    }
+#ifdef RCDEBUG
+    if (pDpa->shutdown || pDpa->reboot)
+        printk("rc: xmit callback: shutdown||reboot\n");
+#endif
+
+#ifdef RCDEBUG     
+    printk("rc: xmit_callback: PcktCount = %d, BC = 0x%x\n", 
+            (uint)PcktCount, (uint)BufferContext);
+#endif
+    while (PcktCount--)
+    {
+        skb = (struct sk_buff *)(BufferContext[0]);
+#ifdef RCDEBUG
+        printk("rc: skb = 0x%x\n", (uint)skb);
+#endif
+        BufferContext++;
+        dev_kfree_skb(skb);
+    }
+    dev->tbusy = 0;
+
+}
+
+static void
+RCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+{
+     PDPA pDpa;
+     struct device *dev;
+     
+     pDpa = PCIAdapters[AdapterID];
+     dev = pDpa->dev;
+#ifdef RCDEBUG
+      printk("rc: RCreset_callback Status 0x%x\n", (uint)Status);
+#endif
+      /*
+       * Check to see why we were called.
+       */
+      if (pDpa->shutdown)
+      {
+           printk("rc: Shutting down interface\n");
+           pDpa->shutdown = 0;
+           pDpa->reboot = 0;
+           MOD_DEC_USE_COUNT; 
+      }
+      else if (pDpa->reboot)
+      {
+           printk("rc: reboot, shutdown adapter\n");
+           /*
+            * We don't set any of the flags in RCShutdownLANCard()
+            * and we don't pass a callback routine to it.
+            * The adapter will have already initiated the reboot by
+            * the time the function returns.
+            */
+		   RCDisableAdapterInterrupts(pDpa->id);
+           RCShutdownLANCard(pDpa->id,0,0,0);
+           printk("rc: scheduling timer...\n");
+           init_timer(&pDpa->timer);
+           pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
+           pDpa->timer.data = (unsigned long)dev;
+           pDpa->timer.function = &rc_timer;    /* timer handler */
+           add_timer(&pDpa->timer);
+      }
+
+
+
+}
+
+static void
+RCreboot_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+{
+     PDPA pDpa;
+    
+     pDpa = PCIAdapters[AdapterID];
+#ifdef RCDEBUG
+     printk("rc: RCreboot: rcv buffers outstanding = %d\n", 
+            (uint)pDpa->numOutRcvBuffers);
+#endif
+     if (pDpa->shutdown)
+     {
+          printk("rc: skipping reboot sequence -- shutdown already initiated\n");
+          return;
+     }
+     pDpa->reboot = 1;
+     /*
+      * OK, we reset the adapter and ask it to return all
+      * outstanding transmit buffers as well as the posted
+      * receive buffers.  When the adapter is done returning
+      * those buffers, it will call our RCreset_callback() 
+      * routine.  In that routine, we'll call RCShutdownLANCard()
+      * to tell the adapter that it's OK to start the reboot and
+      * schedule a timer callback routine to execute 3 seconds 
+      * later; this routine will reinitialize the adapter at that time.
+      */
+     RCResetLANCard(pDpa->id, 
+                    RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
+                    RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
+                    (PFNCALLBACK)RCreset_callback);
+}
+
+
+int broadcast_packet(unsigned char * address)
+{
+    int i;
+    for (i=0; i<6; i++)
+        if (address[i] != 0xff) return 0;
+
+    return 1;
+}
+
+/*
+ * RCrecv_callback()
+ * 
+ * The receive packet callback routine.  This is called by
+ * RCProcMsgQ() after the adapter posts buffers which have been
+ * filled (one ethernet packet per buffer).
+ */
+static void
+RCrecv_callback(U32  Status, 
+                U8   PktCount, 
+                U32  BucketsRemain, 
+                PU32 PacketDescBlock, 
+                U16  AdapterID)
+{
+
+     U32 len, count;
+     PDPA pDpa;
+     struct sk_buff *skb;
+     struct device *dev;
+     singleTCB tcb;
+     psingleTCB ptcb = &tcb;
+
+
+          pDpa = PCIAdapters[AdapterID];
+          dev = pDpa->dev;
+
+          ptcb->bcount = 1;
+
+#ifdef RCDEBUG
+          printk("rc: RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
+                 (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);
+#endif
+        
+#ifdef RCDEBUG
+          if ((pDpa->shutdown || pDpa->reboot) && !Status)
+               printk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
+#endif
+
+          if ( (Status != RC_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
+          {
+               /*
+                * Free whatever buffers the adapter returned, but don't
+                * pass them to the kernel.
+                */
+        
+                    if (!pDpa->shutdown && !pDpa->reboot)
+                         printk("rc: RCrecv error: status = 0x%x\n", (uint)Status);
+                    else
+                         printk("rc: Returning %d buffers, status = 0x%x\n", 
+                                PktCount, (uint)Status);
+               /*
+                * TO DO: check the nature of the failure and put the adapter in
+                * failed mode if it's a hard failure.  Send a reset to the adapter
+                * and free all outstanding memory.
+                */
+               if (Status == RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
+               {
+#ifdef RCDEBUG
+                    printk("RCrecv status ABORT NO DATA TRANSFER\n");
+#endif
+               }
+               /* check for reset status: RC_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */ 
+               if (PacketDescBlock)
+               {
+                    while(PktCount--)
+                    {
+                         skb = (struct sk_buff *)PacketDescBlock[0];
+#ifdef RCDEBUG
+                         printk("free skb 0x%p\n", skb);
+#endif
+                         dev_kfree_skb(skb);
+                         pDpa->numOutRcvBuffers--;
+                         PacketDescBlock += BD_SIZE; /* point to next context field */
+                    }
+               }
+               return;
+          }
+          else
+          {
+               while(PktCount--)
+               {
+                    skb = (struct sk_buff *)PacketDescBlock[0];
+#ifdef RCDEBUG
+                    if (pDpa->shutdown)
+                         printk("shutdown: skb=0x%x\n", (uint)skb);
+
+                    printk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
+                           (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2],
+                           (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);
+#endif
+                    if ( (memcmp(dev->dev_addr, skb->data, 6)) &&
+                         (!broadcast_packet(skb->data)))
+                    {
+                         /*
+                          * Re-post the buffer to the adapter.  Since the adapter usually
+                          * return 1 to 2 receive buffers at a time, it's not too inefficient
+                          * post one buffer at a time but ... may be that should be 
+                          * optimized at some point.
+                          */
+                         ptcb->b.context = (U32)skb;    
+                         ptcb->b.scount = 1;
+                         ptcb->b.size = MAX_ETHER_SIZE;
+                         ptcb->b.addr = (U32)skb->data;
+
+                         if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
+                         {
+                              printk("rc: RCrecv_callback: post buffer failed!\n");
+                              dev_kfree_skb(skb);
+                         }
+                         else
+                         {
+                              pDpa->numOutRcvBuffers++;
+                         }
+                    }
+                    else
+                    {
+                         len = PacketDescBlock[2];
+                         skb->dev = dev;
+                         skb_put( skb, len ); /* adjust length and tail */
+                         skb->protocol = eth_type_trans(skb, dev);
+                         netif_rx(skb);    /* send the packet to the kernel */
+                         dev->last_rx = jiffies;
+                    }
+                    pDpa->numOutRcvBuffers--;
+                    PacketDescBlock += BD_SIZE; /* point to next context field */
+               }
+          } 
+    
+          /*
+           * Replenish the posted receive buffers. 
+           * DO NOT replenish buffers if the driver has already
+           * initiated a reboot or shutdown!
+           */
+
+          if (!pDpa->shutdown && !pDpa->reboot)
+          {
+               count = RC_allocate_and_post_buffers(dev, 
+                                                    MAX_NMBR_RCV_BUFFERS-pDpa->numOutRcvBuffers);
+               pDpa->numOutRcvBuffers += count;
+          }
+
+}
+
+/*
+ * RCinterrupt()
+ * 
+ * Interrupt handler. 
+ * This routine sets up a couple of pointers and calls
+ * RCProcMsgQ(), which in turn process the message and
+ * calls one of our callback functions.
+ */
+static void 
+RCinterrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+     PDPA pDpa;
+     struct device *dev = (struct device *)(dev_id);
+
+     pDpa = (PDPA) (dev->priv);
+     
+     if (pDpa->shutdown)
+          printk("rc: shutdown: service irq\n");
+
+#ifdef RCDEBUG
+     printk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", 
+            (uint)pDpa, (uint)dev, (uint)pDpa->id);
+     printk("dev = 0x%x\n", (uint)dev);
+#endif
+     if (dev->interrupt)
+          printk("%s: Re-entering the interrupt handler.\n", dev->name);
+     dev->interrupt = 1;
+
+     RCProcMsgQ(pDpa->id);
+     dev->interrupt = 0;
+
+     return;
+}
+
+#define REBOOT_REINIT_RETRY_LIMIT 10
+static void rc_timer(unsigned long data)
+{
+     struct device *dev = (struct device *)data;
+     PDPA pDpa = (PDPA) (dev->priv);
+     int init_status;
+     static int retry = 0;
+     int post_buffers = MAX_NMBR_RCV_BUFFERS;
+     int count = 0;
+     int requested = 0;
+
+     if (pDpa->reboot)
+     {
+
+          init_status = InitRCApiMsgLayer(pDpa->id, dev->base_addr, 
+                                          pDpa->PLanApiPA, pDpa->PLanApiPA,
+                                          (PFNTXCALLBACK)RCxmit_callback,
+                                          (PFNRXCALLBACK)RCrecv_callback,
+                                          (PFNCALLBACK)RCreboot_callback);
+
+          switch(init_status)
+          {
+          case RC_RTN_NO_ERROR:
+ 
+               pDpa->reboot = 0;
+               pDpa->shutdown = 0;        /* just in case */
+               RCReportDriverCapability(pDpa->id, DriverControlWord);
+               RCEnableAdapterInterrupts(pDpa->id);
+
+               if (dev->flags & IFF_UP)
+               {
+                    while(post_buffers)
+                    {
+                         if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+                              requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
+                         else
+                              requested = post_buffers;
+                         count = RC_allocate_and_post_buffers(dev, requested);
+                         post_buffers -= count;
+                         if ( count < requested )
+                              break;
+                    }
+                    pDpa->numOutRcvBuffers = 
+                         MAX_NMBR_RCV_BUFFERS - post_buffers;
+                    printk("rc: posted %d buffers \r\n", 
+                           (uint)pDpa->numOutRcvBuffers);
+               }
+               printk("rc: Initialization done.\n");
+               return;
+          case RC_RTN_FREE_Q_EMPTY:
+               retry++;
+               printk("rc: inbound free q emtpy\n");
+               break;
+          default:
+               retry++;
+               printk("rc: unexpected bad status after reboot\n");    
+               break;
+          }
+
+          if (retry > REBOOT_REINIT_RETRY_LIMIT)
+          {
+               printk("rc: unable to reinitialize adapter after reboot\n");
+               printk("rc: decrementing driver and closing interface\n");
+               RCDisableAdapterInterrupts(pDpa->id);
+               dev->flags &= ~IFF_UP;
+               MOD_DEC_USE_COUNT; 
+          }
+          else
+          {
+               printk("rc: rescheduling timer...\n");
+               init_timer(&pDpa->timer);
+               pDpa->timer.expires = RUN_AT((30*HZ)/10); /* 3 sec. */
+               pDpa->timer.data = (unsigned long)dev;
+               pDpa->timer.function = &rc_timer;    /* timer handler */
+               add_timer(&pDpa->timer);
+          }
+     }
+     else
+     {
+          printk("rc: timer??\n");
+     }
+}
+
+static int
+RCclose(struct device *dev)
+{
+
+     PDPA pDpa = (PDPA) dev->priv;
+
+#ifdef RCDEBUG
+     printk("rc: RCclose\r\n");
+#endif
+     if (pDpa->reboot)
+     {
+          printk("rc: skipping reset -- adapter already in reboot mode\n");
+          dev->flags &= ~IFF_UP;
+          pDpa->shutdown = 1;
+          return 0;
+     }
+#ifdef RCDEBUG
+     printk("rc: receive buffers outstanding: %d\n", 
+            (uint)pDpa->numOutRcvBuffers);
+#endif
+
+     pDpa->shutdown = 1;
+
+     /*
+      * We can't allow the driver to be unloaded until the adapter returns
+      * all posted receive buffers.  It doesn't hurt to tell the adapter
+      * to return all posted receive buffers and outstanding xmit buffers,
+      * even if there are none.
+      */
+
+     RCShutdownLANCard(pDpa->id, 
+                       RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
+                       RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
+                       (PFNCALLBACK)RCreset_callback);
+
+     dev->flags &= ~IFF_UP;
+     return 0;
+}
+
+static struct enet_statistics *
+RCget_stats(struct device *dev)
+{
+    RCLINKSTATS    RCstats;
+   
+    PDPA pDpa = dev->priv;
+
+    if (!pDpa)
+    {
+        printk("rc: RCget_stats: !pDpa\n");
+        return 0;
+    }
+    else if (!(dev->flags & IFF_UP))    
+    {
+#ifdef RCDEBUG
+        printk("rc: RCget_stats: device down\n");
+#endif
+        return 0;
+    }
+
+    memset(&RCstats, 0, sizeof(RCLINKSTATS));
+    if ( (RCGetLinkStatistics(pDpa->id, &RCstats, (void *)0)) == RC_RTN_NO_ERROR )
+    {
+#ifdef RCDEBUG
+        printk("rc: TX_good 0x%x\n", (uint)RCstats.TX_good);
+        printk("rc: TX_maxcol 0x%x\n", (uint)RCstats.TX_maxcol);
+        printk("rc: TX_latecol 0x%x\n", (uint)RCstats.TX_latecol);
+        printk("rc: TX_urun 0x%x\n", (uint)RCstats.TX_urun);
+        printk("rc: TX_crs 0x%x\n", (uint)RCstats.TX_crs);
+        printk("rc: TX_def 0x%x\n", (uint)RCstats.TX_def);
+        printk("rc: TX_singlecol 0x%x\n", (uint)RCstats.TX_singlecol);
+        printk("rc: TX_multcol 0x%x\n", (uint)RCstats.TX_multcol);
+        printk("rc: TX_totcol 0x%x\n", (uint)RCstats.TX_totcol);
+
+        printk("rc: Rcv_good 0x%x\n", (uint)RCstats.Rcv_good);
+        printk("rc: Rcv_CRCerr 0x%x\n", (uint)RCstats.Rcv_CRCerr);
+        printk("rc: Rcv_alignerr 0x%x\n", (uint)RCstats.Rcv_alignerr);
+        printk("rc: Rcv_reserr 0x%x\n", (uint)RCstats.Rcv_reserr);
+        printk("rc: Rcv_orun 0x%x\n", (uint)RCstats.Rcv_orun);
+        printk("rc: Rcv_cdt 0x%x\n", (uint)RCstats.Rcv_cdt);
+        printk("rc: Rcv_runt 0x%x\n", (uint)RCstats.Rcv_runt);
+#endif
+
+        pDpa->stats.rx_packets = RCstats.Rcv_good; /* total packets received    */
+        pDpa->stats.tx_packets = RCstats.TX_good; /* total packets transmitted    */
+
+        pDpa->stats.rx_errors = 
+            RCstats.Rcv_CRCerr +
+            RCstats.Rcv_alignerr + 
+            RCstats.Rcv_reserr + 
+            RCstats.Rcv_orun + 
+            RCstats.Rcv_cdt + 
+            RCstats.Rcv_runt; /* bad packets received        */
+
+        pDpa->stats.tx_errors = 
+            RCstats.TX_urun + 
+            RCstats.TX_crs + 
+            RCstats.TX_def + 
+            RCstats.TX_totcol; /* packet transmit problems    */
+
+        /*
+         * This needs improvement.
+         */
+        pDpa->stats.rx_dropped = 0;        /* no space in linux buffers    */
+        pDpa->stats.tx_dropped = 0;        /* no space available in linux    */
+        pDpa->stats.multicast = 0;        /* multicast packets received    */
+        pDpa->stats.collisions = RCstats.TX_totcol;
+
+        /* detailed rx_errors: */
+        pDpa->stats.rx_length_errors = 0;
+        pDpa->stats.rx_over_errors = RCstats.Rcv_orun; /* receiver ring buff overflow    */
+        pDpa->stats.rx_crc_errors = RCstats.Rcv_CRCerr;    /* recved pkt with crc error    */
+        pDpa->stats.rx_frame_errors = 0; /* recv'd frame alignment error */
+        pDpa->stats.rx_fifo_errors = 0; /* recv'r fifo overrun        */
+        pDpa->stats.rx_missed_errors = 0; /* receiver missed packet    */
+
+        /* detailed tx_errors */
+        pDpa->stats.tx_aborted_errors = 0;
+        pDpa->stats.tx_carrier_errors = 0;
+        pDpa->stats.tx_fifo_errors = 0;
+        pDpa->stats.tx_heartbeat_errors = 0;
+        pDpa->stats.tx_window_errors = 0;
+
+        return ((struct enet_statistics *)&(pDpa->stats));
+    }
+    return 0;
+}
+
+static int RCioctl(struct device *dev, struct ifreq *rq, int cmd)
+{
+    RCuser_struct RCuser;
+    PDPA pDpa = dev->priv;
+
+#if RCDEBUG
+    printk("RCioctl: cmd = 0x%x\n", cmd);
+#endif
+ 
+    switch (cmd)  {
+ 
+        case RCU_PROTOCOL_REV:
+             /*
+              * Assign user protocol revision, to tell user-level
+              * controller program whether or not it's in sync.
+              */
+             rq->ifr_ifru.ifru_data = (caddr_t) USER_PROTOCOL_REV;
+             break;
+  
+
+        case RCU_COMMAND:
+        {
+            if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
+            	return -EFAULT;
+        
+#ifdef RCDEBUG
+            printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
+#endif
+  
+            switch(RCuser.cmd)
+            {
+                case RCUC_GETFWVER:
+                    printk("RC GETFWVER\n");
+                    RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
+                    RCGetFirmwareVer(pDpa->id, (PU8) &RCUD_GETFWVER->FirmString, NULL);
+                    break;
+                case RCUC_GETINFO:
+                    printk("RC GETINFO\n");
+                    RCUD_GETINFO = &RCuser.RCUS_GETINFO;
+                    RCUD_GETINFO -> mem_start = dev->base_addr;
+                    RCUD_GETINFO -> mem_end = dev->base_addr + 32768;
+                    RCUD_GETINFO -> base_addr = pDpa->pci_addr;
+                    RCUD_GETINFO -> irq = dev->irq;
+                    break;
+                case RCUC_GETIPANDMASK:
+                    printk("RC GETIPANDMASK\n");
+                    RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
+                    RCGetRavlinIPandMask(pDpa->id, (PU32) &RCUD_GETIPANDMASK->IpAddr,
+                        (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
+                    break;
+                case RCUC_GETLINKSTATISTICS:
+                    printk("RC GETLINKSTATISTICS\n");
+                    RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS;
+                    RCGetLinkStatistics(pDpa->id, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
+                    break;
+                case RCUC_GETLINKSTATUS:
+                    printk("RC GETLINKSTATUS\n");
+                    RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
+                    RCGetLinkStatus(pDpa->id, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
+                    break;
+                case RCUC_GETMAC:
+                    printk("RC GETMAC\n");
+                    RCUD_GETMAC = &RCuser.RCUS_GETMAC;
+                    RCGetMAC(pDpa->id, (PU8) &RCUD_GETMAC->mac, NULL);
+                    break;
+                case RCUC_GETSPEED:
+                    printk("RC GETSPEED\n");
+                    if (!(dev->flags & IFF_UP))    
+                    {
+                        printk("RCioctl, GETSPEED error: interface down\n");
+                        return -ENODATA;
+                    }
+                    RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
+                    RCGetLinkSpeed(pDpa->id, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
+                    printk("RC speed = 0x%ld\n", RCUD_GETSPEED->LinkSpeedCode);
+                    break;
+                default:
+                    printk("RC command default\n");
+                    RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
+                    RCUD_DEFAULT -> rc = 0x11223344;
+                    break;
+            }
+            copy_to_user(rq->ifr_data, &RCuser, sizeof(RCuser));
+            break;
+        }   /* RCU_COMMAND */ 
+
+        default:
+            printk("RC default\n");
+            rq->ifr_ifru.ifru_data = (caddr_t) 0x12345678;
+            break;
+    }
+    return 0;
+}
+
+static int RCconfig(struct device *dev, struct ifmap *map)
+{
+     /*
+      * To be completed ...
+      */
+      printk("rc: RCconfig\n");
+      return 0;
+      if (dev->flags & IFF_UP)    /* can't act on a running interface */
+           return -EBUSY;
+
+     /* Don't allow changing the I/O address */
+     if (map->base_addr != dev->base_addr) {
+          printk(KERN_WARNING "RC pci45: Change I/O address not implemented\n");
+          return -EOPNOTSUPP;
+     }
+     return 0;
+}
+
+#ifdef MODULE
+void cleanup_module(void)
+{
+     PDPA pDpa;
+     struct device *next;
+
+
+#ifdef RCDEBUG
+     printk("rc: RC cleanup_module\n");
+     printk("rc: root_RCdev = 0x%x\n", (uint)root_RCdev);
+#endif
+
+
+     while (root_RCdev)
+     {
+          pDpa = (PDPA) root_RCdev->priv;
+#ifdef RCDEBUG
+          printk("rc: cleanup 0x%08X\n", (uint)root_RCdev);
+#endif
+          printk("Adapter reset: 0x%x\n", RCResetAdapter(pDpa->id));
+          unregister_netdev(root_RCdev);
+          next = pDpa->next;
+
+          vfree((unsigned long *)root_RCdev->base_addr); 
+          free_irq( root_RCdev->irq, root_RCdev );
+          kfree(root_RCdev);
+          root_RCdev = next;
+     }
+}
+#endif
+
+
+static int
+RC_allocate_and_post_buffers(struct device *dev, int numBuffers)
+{
+
+     int i;
+     PDPA pDpa = (PDPA)dev->priv;
+     PU32 p;
+     psingleB pB;
+     struct sk_buff *skb;
+     RC_RETURN status;
+
+     if (!numBuffers)
+          return 0;
+     else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
+     {
+#ifdef RCDEBUG
+          printk("rc: Too many buffers requested!\n");
+          printk("rc: attempting to allocate only 32 buffers\n");
+#endif
+          numBuffers = 32;
+     }
+    
+     p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
+
+#ifdef RCDEBUG
+     printk("rc: TCB = 0x%x\n", (uint)p);
+#endif
+
+     if (!p)
+     {
+          printk("rc: RCopen: unable to allocate TCB\n");
+          return 0;
+     }
+
+     p[0] = 0;                              /* Buffer Count */
+     pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+
+#ifdef RCDEBUG
+     printk("rc: p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
+     printk("rc: pB = 0x%x\n", (uint)pB);
+#endif
+
+     for (i=0; i<numBuffers; i++)
+     {
+          skb = dev_alloc_skb(MAX_ETHER_SIZE+2);
+          if (!skb)
+          {
+               printk("rc: Doh! RCopen: unable to allocate enough skbs!\n");
+               if (*p != 0)        /* did we allocate any buffers at all? */
+               {
+#ifdef RCDEBUG
+                    printk("rc: will post only %d buffers \n", (uint)(*p));
+#endif
+                    break;
+               }
+               else 
+               {
+                    kfree(p);    /* Free the TCB */
+                    return 0;
+               }
+          }
+#ifdef RCDEBUG
+          printk("post 0x%x\n", (uint)skb);
+#endif
+          skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
+          pB->context = (U32)skb;
+          pB->scount = 1;        /* segment count */
+          pB->size = MAX_ETHER_SIZE;
+          pB->addr = (U32)skb->data;
+          p[0]++;
+          pB++;
+     }
+
+     if ( (status = RCPostRecvBuffers(pDpa->id, (PRCTCB)p )) != RC_RTN_NO_ERROR)
+     {
+          printk("rc: Post buffer failed with error code 0x%x!\n", status);
+          pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
+          while(p[0])
+          {
+               skb = (struct sk_buff *)pB->context;
+#ifdef RCDEBUG
+               printk("rc: freeing 0x%x\n", (uint)skb);
+#endif
+               dev_kfree_skb(skb);
+               p[0]--;
+               pB++;
+          }
+#ifdef RCDEBUG
+           printk("rc: freed all buffers, p[0] = %ld\n", p[0]);
+#endif
+     }
+     kfree(p);
+     return(p[0]);                /* return the number of posted buffers */
+}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c
--- v2.1.131/linux/drivers/net/rrunner.c	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/rrunner.c	Thu Dec 17 09:04:49 1998
@@ -39,9 +39,11 @@
 #include <asm/byteorder.h>
 #include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/uaccess.h>
 
 #include "rrunner.h"
 
+
 /*
  * Implementation notes:
  *
@@ -57,7 +59,7 @@
  * stack will need to know about I/O vectors or something similar.
  */
 
-static const char *version = "rrunner.c: v0.06 09/02/98  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
+static const char *version = "rrunner.c: v0.09 12/14/98  Jes Sorensen (Jes.Sorensen@cern.ch)\n";
 
 static unsigned int read_eeprom(struct rr_private *rrpriv,
 				unsigned long offset,
@@ -68,6 +70,14 @@
 static int rr_load_firmware(struct device *dev);
 
 
+/*
+ * These are checked at init time to see if they are at least 256KB
+ * and increased to 256KB if they are not. This is done to avoid ending
+ * up with socket buffers smaller than the MTU size,
+ */
+extern __u32 sysctl_wmem_max;
+extern __u32 sysctl_rmem_max;
+
 __initfunc(int rr_hippi_probe (struct device *dev))
 {
 	static int i = 0;
@@ -116,6 +126,9 @@
 		if (dev == NULL)
 			break;
 
+		if (!dev->priv)
+			dev->priv = kmalloc(sizeof(*rrpriv), GFP_KERNEL);
+
 		rrpriv = (struct rr_private *)dev->priv;
 
 		/* Read register base address from
@@ -194,12 +207,8 @@
 		rr_init(dev);
 
 		boards_found++;
-
-		/*
-		 * This is bollocks, but we need to tell the net-init
-		 * code that it shall go for the next device.
-		 */
 		dev->base_addr = 0;
+		dev = NULL;
 	}
 
 	/*
@@ -347,6 +356,7 @@
 	return 0;
 }
 
+
 /*
  * Read a string from the EEPROM.
  */
@@ -356,18 +366,21 @@
 				unsigned long length)
 {
 	struct rr_regs *regs = rrpriv->regs;
-	u32 misc, io, i;
+	u32 misc, io, host, i;
 
 	io = regs->ExtIo;
 	regs->ExtIo = 0;
 	misc = regs->LocalCtrl;
 	regs->LocalCtrl = 0;
+	host = regs->HostCtrl;
+	regs->HostCtrl |= HALT_NIC;
 
 	for (i = 0; i < length; i++){
 		regs->WinBase = (EEPROM_BASE + ((offset+i) << 3));
 		buf[i] = (regs->WinData >> 24) & 0xff;
 	}
 
+	regs->HostCtrl = host;
 	regs->LocalCtrl = misc;
 	regs->ExtIo = io;
 
@@ -391,6 +404,58 @@
 }
 
 
+/*
+ * Write a string to the EEPROM.
+ *
+ * This is only called when the firmware is not running.
+ */
+static unsigned int write_eeprom(struct rr_private *rrpriv,
+				unsigned long offset,
+				unsigned char *buf,
+				unsigned long length)
+{
+	struct rr_regs *regs = rrpriv->regs;
+	u32 misc, io, data, i, j, ready, error = 0;
+
+	io = regs->ExtIo;
+	regs->ExtIo = 0;
+	misc = regs->LocalCtrl;
+	regs->LocalCtrl = ENABLE_EEPROM_WRITE;
+
+	for (i = 0; i < length; i++){
+		regs->WinBase = (EEPROM_BASE + ((offset+i) << 3));
+		data = buf[i] << 24;
+		/*
+		 * Only try to write the data if it is not the same
+		 * value already.
+		 */
+		if ((regs->WinData & 0xff000000) != data){
+			regs->WinData = data;
+			ready = 0;
+			j = 0;
+			mb();
+			while(!ready){
+				udelay(1000);
+				if ((regs->WinData & 0xff000000) == data)
+					ready = 1;
+				if (j++ > 5000){
+					printk("data mismatch: %08x, "
+					       "WinData %08x\n", data,
+					       regs->WinData);
+					ready = 1;
+					error = 1;
+				}
+			}
+		}
+	}
+
+	regs->LocalCtrl = misc;
+	regs->ExtIo = io;
+
+	return error;
+}
+
+
 __initfunc(static int rr_init(struct device *dev))
 {
 	struct rr_private *rrpriv;
@@ -404,8 +469,13 @@
 	if (rev > 0x00020024)
 		printk("  Firmware revision: %i.%i.%i\n", (rev >> 16),
 		       ((rev >> 8) & 0xff), (rev & 0xff));
-	else{
-		printk("  Firmware revision too old: %i.%i.%i, please upgrade to 2.0.37 or later.\n",
+	else if (rev >= 0x00020000) {
+		printk("  Firmware revision: %i.%i.%i (2.0.37 or "
+		       "later is recommended)\n", (rev >> 16),
+		       ((rev >> 8) & 0xff), (rev & 0xff));
+	}else{
+		printk("  Firmware revision too old: %i.%i.%i, please "
+		       "upgrade to 2.0.37 or later.\n",
 		       (rev >> 16), ((rev >> 8) & 0xff), (rev & 0xff));
 		return -EFAULT;
 		
@@ -416,6 +486,18 @@
 	sram_size = read_eeprom_word(rrpriv, (void *)8);
 	printk("  SRAM size 0x%06x\n", sram_size);
 
+	if (sysctl_rmem_max < 262144){
+		printk("  Receive socket buffer limit too low (%i), "
+		       "setting to 262144\n", sysctl_rmem_max);
+		sysctl_rmem_max = 262144;
+	}
+
+	if (sysctl_wmem_max < 262144){
+		printk("  Transmit socket buffer limit too low (%i), "
+		       "setting to 262144\n", sysctl_wmem_max);
+		sysctl_wmem_max = 262144;
+	}
+
 	return 0;
 }
 
@@ -574,7 +656,9 @@
 }
 #endif
 	dev->tbusy = 0;
+#if 0
 	dev->interrupt = 0;
+#endif
 	dev->start = 1;
 	return 0;
 }
@@ -590,9 +674,6 @@
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
 	u32 tmp, eidx;
-#if 0
-	short i;
-#endif
 
 	rrpriv = (struct rr_private *)dev->priv;
 	regs = rrpriv->regs;
@@ -710,7 +791,8 @@
 			if (pkt_len < PKT_COPY_THRESHOLD) {
 				skb = alloc_skb(pkt_len, GFP_ATOMIC);
 				if (skb == NULL){
-					printk("%s: Out of memory deferring packet\n", dev->name);
+					printk("%s: Out of memory deferring "
+					       "packet\n", dev->name);
 					rrpriv->stats.rx_dropped++;
 					goto defer;
 				}else
@@ -720,14 +802,16 @@
 			}else{
 				struct sk_buff *newskb;
 
-				newskb = alloc_skb(dev->mtu + HIPPI_HLEN, GFP_ATOMIC);
+				newskb = alloc_skb(dev->mtu + HIPPI_HLEN,
+						   GFP_ATOMIC);
 				if (newskb){
 					skb = rrpriv->rx_skbuff[index];
 					skb_put(skb, pkt_len);
 					rrpriv->rx_skbuff[index] = newskb;
 					rrpriv->rx_ring[index].addr = virt_to_bus(newskb->data);
 				}else{
-					printk("%s: Out of memory, deferring packet\n", dev->name);
+					printk("%s: Out of memory, deferring "
+					       "packet\n", dev->name);
 					rrpriv->stats.rx_dropped++;
 					goto defer;
 				}
@@ -766,18 +850,15 @@
 	rrpriv = (struct rr_private *)dev->priv;
 	regs = rrpriv->regs;
 
-	if (!(regs->HostCtrl & RR_INT)){
-#if 0
-		/* These are harmless */
-		printk("%s: spurious interrupt detected\n", dev->name);
-#endif
+	if (!(regs->HostCtrl & RR_INT))
 		return;
-	}
 
+#if 0
 	if (test_and_set_bit(0, (void*)&dev->interrupt) != 0) {
 		printk("%s: Re-entering the interrupt handler.\n", dev->name);
 		return;
 	}
+#endif
 
 	spin_lock_irqsave(&rrpriv->lock, flags);
 
@@ -828,7 +909,9 @@
 
 	spin_unlock_irqrestore(&rrpriv->lock, flags);
 
+#if 0
 	dev->interrupt = 0;
+#endif
 }
 
 
@@ -844,7 +927,7 @@
 	regs->HostCtrl |= (HALT_NIC | RR_CLEAR_INT);
 #endif
 
-	if (request_irq(dev->irq, rr_interrupt, 0, rrpriv->name, dev))
+	if (request_irq(dev->irq, rr_interrupt, SA_SHIRQ, rrpriv->name, dev))
 	{
 		printk(KERN_WARNING "%s: Requested IRQ %d is busy\n",
 		       dev->name, dev->irq);
@@ -858,7 +941,9 @@
 	rr_init1(dev);
 
 	dev->tbusy = 0;
+#if 0
 	dev->interrupt = 0;
+#endif
 	dev->start = 1;
 
 	MOD_INC_USE_COUNT;
@@ -942,6 +1027,12 @@
 	rrpriv = (struct rr_private *)dev->priv;
 	regs = rrpriv->regs;
 
+	/*
+	 * Lock to make sure we are not cleaning up while another CPU
+	 * handling interrupts.
+	 */
+	spin_lock(&rrpriv->lock);
+
 	tmp = regs->HostCtrl;
 	if (tmp & NIC_HALTED){
 		printk("%s: NIC already halted\n", dev->name);
@@ -950,11 +1041,7 @@
 		tmp |= HALT_NIC;
 	regs->HostCtrl = tmp;
 
-	/*
-	 * Lock to make sure we are not cleaning up while another CPU
-	 * handling interrupts.
-	 */
-	spin_lock(&rrpriv->lock);
+	rrpriv->fw_running = 0;
 
 	regs->TxPi = 0;
 	regs->IpRxPi = 0;
@@ -1080,9 +1167,6 @@
 {
 	struct rr_private *rrpriv;
 	struct rr_regs *regs;
-#if 0
-	unsigned long flags;
-#endif
 	int i, j;
 	u32 localctrl, eptr, sptr, segptr, len, tmp;
 	u32 p2len, p2size, nr_seg, revision, io, sram_size;
@@ -1179,30 +1263,117 @@
 static int rr_ioctl(struct device *dev, struct ifreq *rq, int cmd)
 {
 	struct rr_private *rrpriv;
+	unsigned char *image, *oldimage;
+	unsigned int i;
+	int error = -EOPNOTSUPP;
 
 	rrpriv = (struct rr_private *)dev->priv;
 
+	spin_lock(&rrpriv->lock);
+
 	switch(cmd){
+	case SIOCRRGFW:
+		if (!suser()){
+			error = -EPERM;
+			goto out;
+		}
+
+		if (rrpriv->fw_running){
+			printk("%s: Firmware already running\n", dev->name);
+			error = -EPERM;
+			goto out;
+		}
+
+		image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+		if (!image){
+			printk(KERN_ERR "%s: Unable to allocate memory "
+			       "for EEPROM image\n", dev->name);
+			error = -ENOMEM;
+			goto out;
+		}
+		i = read_eeprom(rrpriv, 0, image, EEPROM_BYTES);
+		if (i != EEPROM_BYTES){
+			kfree(image);
+			printk(KERN_ERR "%s: Error reading EEPROM\n",
+			       dev->name);
+			error = -EFAULT;
+			goto out;
+		}
+		error = copy_to_user(rq->ifr_data, image, EEPROM_BYTES);
+		if (error)
+			error = -EFAULT;
+		kfree(image);
+		break;
 	case SIOCRRPFW:
-		if (!suser())
-			return -EPERM;
+		if (!suser()){
+			error = -EPERM;
+			goto out;
+		}
 
 		if (rrpriv->fw_running){
-			printk("%s: firmware already running\n", dev->name);
-			return -EPERM;
+			printk("%s: Firmware already running\n", dev->name);
+			error = -EPERM;
+			goto out;
+		}
+
+		image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+		if (!image){
+			printk(KERN_ERR "%s: Unable to allocate memory "
+			       "for EEPROM image\n", dev->name);
+			error = -ENOMEM;
+			goto out;
+		}
+
+		oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
+		if (!image){
+			printk(KERN_ERR "%s: Unable to allocate memory "
+			       "for old EEPROM image\n", dev->name);
+			error = -ENOMEM;
+			goto out;
 		}
-		printk("%s: updating firmware", dev->name);
+
+		error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
+		if (error)
+			error = -EFAULT;
+
+		printk("%s: Updating EEPROM firmware\n", dev->name);
+
+		error = write_eeprom(rrpriv, 0, image, EEPROM_BYTES);
+		if (error)
+			printk(KERN_ERR "%s: Error writing EEPROM\n",
+			       dev->name);
+
+		i = read_eeprom(rrpriv, 0, oldimage, EEPROM_BYTES);
+		if (i != EEPROM_BYTES)
+			printk(KERN_ERR "%s: Error reading back EEPROM "
+			       "image\n", dev->name);
+
+		error = memcmp(image, oldimage, EEPROM_BYTES);
+		if (error){
+			printk(KERN_ERR "%s: Error verifying EEPROM image\n",
+			       dev->name);
+			error = -EFAULT;
+		}
+
+		kfree(image);
+		kfree(oldimage);
+		break;
+	case SIOCRRID:
+		error = put_user(0x52523032, (int *)(&rq->ifr_data[0]));
+		if (error)
+			error = -EFAULT;
 		break;
 	default:
-		return -EOPNOTSUPP;
 	}
 
-	return 0;
+ out:
+	spin_unlock(&rrpriv->lock);
+	return error;
 }
 
 
 /*
  * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c"
+ * compile-command: "gcc -D__SMP__ -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -DCPU=686 -c rrunner.c"
  * End:
  */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/rrunner.h linux/drivers/net/rrunner.h
--- v2.1.131/linux/drivers/net/rrunner.h	Fri Oct  9 13:27:09 1998
+++ linux/drivers/net/rrunner.h	Thu Dec 17 09:04:49 1998
@@ -550,6 +550,7 @@
 
 #define SIOCRRPFW	SIOCDEVPRIVATE		/* put firmware */
 #define SIOCRRGFW	SIOCDEVPRIVATE+1	/* get firmware */
+#define SIOCRRID	SIOCDEVPRIVATE+2	/* identify */
 
 
 struct seg_hdr {
@@ -560,6 +561,8 @@
 
 
 #define EEPROM_BASE 0x80000000
+#define EEPROM_WORDS 8192
+#define EEPROM_BYTES (EEPROM_WORDS * sizeof(u32))
 
 struct eeprom_boot {
 	u32	key1;
diff -u --recursive --new-file v2.1.131/linux/drivers/net/slhc.c linux/drivers/net/slhc.c
--- v2.1.131/linux/drivers/net/slhc.c	Fri Jan 30 11:28:07 1998
+++ linux/drivers/net/slhc.c	Fri Dec 18 09:40:56 1998
@@ -51,14 +51,16 @@
  */
 
 #include <linux/config.h>
-#ifdef CONFIG_INET
-/* Entire module is for IP only */
 #include <linux/module.h>
-
 #include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+
+#ifdef CONFIG_INET
+/* Entire module is for IP only */
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/string.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/termios.h>
@@ -72,7 +74,6 @@
 #include <net/tcp.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
-#include <linux/errno.h>
 #include <linux/timer.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -758,4 +759,52 @@
 }
 
 #endif /* MODULE */
+#else /* CONFIG_INET */
+EXPORT_SYMBOL(slhc_init);
+EXPORT_SYMBOL(slhc_free);
+EXPORT_SYMBOL(slhc_remember);
+EXPORT_SYMBOL(slhc_compress);
+EXPORT_SYMBOL(slhc_uncompress);
+EXPORT_SYMBOL(slhc_toss);
+
+int
+slhc_toss(struct slcompress *comp)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_toss");
+  return -EINVAL;
+}
+int
+slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_uncompress");
+  return -EINVAL;
+}
+int
+slhc_compress(struct slcompress *comp, unsigned char *icp, int isize,
+	unsigned char *ocp, unsigned char **cpp, int compress_cid)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_compress");
+  return -EINVAL;
+}
+
+int
+slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_remember");
+  return -EINVAL;
+}
+
+void
+slhc_free(struct slcompress *comp)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_free");
+  return;
+}
+struct slcompress *
+slhc_init(int rslots, int tslots)
+{
+  printk(KERN_DEBUG "Called IP function on non IP-system: slhc_init");
+  return NULL;
+}
+
 #endif /* CONFIG_INET */
diff -u --recursive --new-file v2.1.131/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c
--- v2.1.131/linux/drivers/net/smc-mca.c	Tue Jun  9 11:57:30 1998
+++ linux/drivers/net/smc-mca.c	Wed Dec 16 13:35:49 1998
@@ -375,7 +375,6 @@
 			/* NB: ultra_close_card() does free_irq */
 			int ioaddr = dev->base_addr - ULTRA_NIC_OFFSET;
 			release_region(ioaddr, ULTRA_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.1.131/linux/drivers/net/smc-ultra.c	Tue Jun  9 11:57:30 1998
+++ linux/drivers/net/smc-ultra.c	Wed Dec 16 13:35:49 1998
@@ -483,7 +483,6 @@
 			void *priv = dev->priv;
 			/* NB: ultra_close_card() does free_irq */
 			release_region(ioaddr, ULTRA_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c
--- v2.1.131/linux/drivers/net/smc-ultra32.c	Tue Jun  9 11:57:30 1998
+++ linux/drivers/net/smc-ultra32.c	Wed Dec 16 13:35:49 1998
@@ -413,7 +413,6 @@
 			void *priv = dev->priv;
 			/* NB: ultra32_close_card() does free_irq */
 			release_region(ioaddr, ULTRA32_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/net/via-rhine.c linux/drivers/net/via-rhine.c
--- v2.1.131/linux/drivers/net/via-rhine.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/net/via-rhine.c	Fri Dec 18 09:44:06 1998
@@ -64,18 +64,7 @@
 
 #define PKT_BUF_SZ		1536			/* Size of each temporary Rx buffer.*/
 
-/* Include files, designed to support most kernel versions 2.0.0 and later. */
-#include <linux/version.h>
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
@@ -115,7 +104,6 @@
 #define RUN_AT(x) (jiffies + (x))
 
 #if (LINUX_VERSION_CODE >= 0x20100)
-char kernel_version[] = UTS_RELEASE;
 #else
 #ifndef __alpha__
 #define ioremap vremap
diff -u --recursive --new-file v2.1.131/linux/drivers/net/wd.c linux/drivers/net/wd.c
--- v2.1.131/linux/drivers/net/wd.c	Tue Jun  9 11:57:30 1998
+++ linux/drivers/net/wd.c	Thu Dec 17 09:04:49 1998
@@ -508,7 +508,6 @@
 			int ioaddr = dev->base_addr - WD_NIC_OFFSET;
 			free_irq(dev->irq, dev);
 			release_region(ioaddr, WD_IO_EXTENT);
-			dev->priv = NULL;
 			unregister_netdev(dev);
 			kfree(priv);
 			unlock_8390_module();
diff -u --recursive --new-file v2.1.131/linux/drivers/net/yellowfin.c linux/drivers/net/yellowfin.c
--- v2.1.131/linux/drivers/net/yellowfin.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/net/yellowfin.c	Fri Dec 18 09:45:17 1998
@@ -63,17 +63,7 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT  ((2000*HZ)/1000)
 
-#ifdef MODULE
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
-#include <linux/version.h>
-#else
-#define MOD_INC_USE_COUNT
-#define MOD_DEC_USE_COUNT
-#endif
-
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/string.h>
@@ -93,13 +83,10 @@
 #include <linux/skbuff.h>
 
 /* Kernel compatibility defines, most common to the PCCard package. */
-#include <linux/version.h>		/* Evil, but neccessary */
+#include <linux/version.h>		/* Evil and unneccessary */
 
 #define RUN_AT(x) (jiffies + (x))
 
-#if (LINUX_VERSION_CODE >= 0x20100)
-char kernel_version[] = UTS_RELEASE;
-#endif
 #if (LINUX_VERSION_CODE < 0x20123)
 #define test_and_set_bit(val, addr) set_bit(val, addr)
 #endif
@@ -214,7 +201,7 @@
 static void yellowfin_timer(unsigned long data);
 
 enum capability_flags {HasMII=1, FullTxStatus=2};
-struct chip_info {
+static struct chip_info {
 	u16	vendor_id, device_id, device_id_mask, pci_flags;
 	const char *name;
 	void (*media_timer)(unsigned long data);
diff -u --recursive --new-file v2.1.131/linux/drivers/net/z85230.c linux/drivers/net/z85230.c
--- v2.1.131/linux/drivers/net/z85230.c	Thu Nov 12 16:21:20 1998
+++ linux/drivers/net/z85230.c	Wed Dec 16 13:35:49 1998
@@ -605,7 +605,7 @@
 int z8530_sync_open(struct device *dev, struct z8530_channel *c)
 {
 	c->sync = 1;
-	c->mtu = dev->mtu;
+	c->mtu = dev->mtu+64;
 	c->count = 0;
 	c->skb = NULL;
 	c->skb2 = NULL;
@@ -641,7 +641,7 @@
 	unsigned long flags;
 	
 	c->sync = 1;
-	c->mtu = dev->mtu;
+	c->mtu = dev->mtu+64;
 	c->count = 0;
 	c->skb = NULL;
 	c->skb2 = NULL;
@@ -822,7 +822,7 @@
 {
 	printk("Opening sync interface for TX-DMA\n");
 	c->sync = 1;
-	c->mtu = dev->mtu;
+	c->mtu = dev->mtu+64;
 	c->count = 0;
 	c->skb = NULL;
 	c->skb2 = NULL;
diff -u --recursive --new-file v2.1.131/linux/drivers/pci/oldproc.c linux/drivers/pci/oldproc.c
--- v2.1.131/linux/drivers/pci/oldproc.c	Sun Nov  8 14:03:01 1998
+++ linux/drivers/pci/oldproc.c	Thu Dec 17 00:12:51 1998
@@ -139,7 +139,11 @@
 	DEVICE( MATROX,		MATROX_MYS,	"Mystique"),
 	DEVICE( MATROX,		MATROX_MIL_2,	"Millennium II"),
 	DEVICE( MATROX,		MATROX_MIL_2_AGP,"Millennium II AGP"),
+	DEVICE( MATROX,         MATROX_G200_PCI,"Matrox G200 PCI"),
+	DEVICE( MATROX,         MATROX_G200_AGP,"Matrox G200 AGP"),
 	DEVICE( MATROX,		MATROX_MGA_IMP,	"MGA Impression"),
+	DEVICE( MATROX,         MATROX_G100_MM, "Matrox G100 multi monitor"),
+	DEVICE( MATROX,         MATROX_G100_AGP,"Matrox G100 AGP"),
 	DEVICE( CT,		CT_65545,	"65545"),
 	DEVICE( CT,		CT_65548,	"65548"),
 	DEVICE(	CT,		CT_65550,	"65550"),
@@ -325,6 +329,7 @@
 	DEVICE( VIA,		VIA_82C586_0,	"VT 82C586 Apollo ISA"),
 	DEVICE( VIA,		VIA_82C595,	"VT 82C595 Apollo VP2"),
 	DEVICE( VIA,		VIA_82C597_0,	"VT 82C597 Apollo VP3"),
+	DEVICE( VIA,		VIA_82C598_0,	"VT 82C598 Apollo MVP3"),
 	DEVICE( VIA,		VIA_82C926,	"VT 82C926 Amazon"),
 	DEVICE( VIA,		VIA_82C416,	"VT 82C416MV"),
 	DEVICE( VIA,		VIA_82C595_97,	"VT 82C595 Apollo VP2/97"),
@@ -332,6 +337,7 @@
 	DEVICE( VIA,		VIA_82C586_3,	"VT 82C586B Apollo ACPI"),
 	DEVICE( VIA,		VIA_86C100A,	"VT 86C100A"),
 	DEVICE( VIA,		VIA_82C597_1,	"VT 82C597 Apollo VP3 AGP"),
+	DEVICE( VIA,		VIA_82C598_1,	"VT 82C598 Apollo MVP3 AGP"),
 	DEVICE( VORTEX,		VORTEX_GDT60x0,	"GDT 60x0"),
 	DEVICE( VORTEX,		VORTEX_GDT6000B,"GDT 6000b"),
 	DEVICE( VORTEX,		VORTEX_GDT6x10,	"GDT 6110/6510"),
diff -u --recursive --new-file v2.1.131/linux/drivers/pci/pcisyms.c linux/drivers/pci/pcisyms.c
--- v2.1.131/linux/drivers/pci/pcisyms.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/pci/pcisyms.c	Wed Dec 16 13:35:49 1998
@@ -9,6 +9,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <asm/dma.h>	/* isa_dma_bridge_buggy */
 
 EXPORT_SYMBOL(pcibios_present);
 EXPORT_SYMBOL(pcibios_read_config_byte);
@@ -38,3 +39,10 @@
 
 EXPORT_SYMBOL(pcibios_find_class);
 EXPORT_SYMBOL(pcibios_find_device);
+
+/* Quirk info */
+
+#ifdef CONFIG_PCI_QUIRKS
+EXPORT_SYMBOL(isa_dma_bridge_buggy);
+#endif
+
diff -u --recursive --new-file v2.1.131/linux/drivers/pci/quirks.c linux/drivers/pci/quirks.c
--- v2.1.131/linux/drivers/pci/quirks.c	Thu May  7 22:51:50 1998
+++ linux/drivers/pci/quirks.c	Wed Dec 16 13:35:49 1998
@@ -125,6 +125,25 @@
 	}
 }
 
+/*  The VIA VP2/VP3/MVP3 seem to have some 'features'. There may be a workaround
+    but VIA don't answer queries. If you happen to have good contacts at VIA
+    ask them for me please -- Alan 
+    
+    This appears to be BIOS not version dependant. So presumably there is a 
+    chipset level fix */
+    
+
+int isa_dma_bridge_buggy = 0;		/* Exported */
+    
+__initfunc(static void quirk_isa_dma_hangs(struct pci_dev *dev, int arg))
+{
+	if(!isa_dma_bridge_buggy)
+	{
+		isa_dma_bridge_buggy=1;
+		printk(KERN_INFO "Activating ISA DMA hang workarounds.\n");
+	}
+}
+
 
 typedef void (*quirk_handler)(struct pci_dev *, int);
 
@@ -141,7 +160,8 @@
 #ifdef CONFIG_PCI_OPTIMIZE
 	{ quirk_bridge,		"Bridge optimization" },
 #endif
-	{ quirk_passive_release, "Passive release enable" },
+	{ quirk_passive_release,"Passive release enable" },
+	{ quirk_isa_dma_hangs,	"Work around ISA DMA hangs" },
 };
 
 
@@ -176,6 +196,12 @@
 	{ PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82430,	quirk_bridge,	0x00 },
 #endif
 	{ PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release,	0x00 },
+	/*
+	 * Its not totally clear which chipsets are the problematic ones
+	 * This is the 82C586 variants. At the moment the 596 is an unknown
+	 * quantity 
+	 */
+	{ PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_82C586_0,	quirk_isa_dma_hangs,	0x00 },
 };
 
 __initfunc(void pci_quirks_init(void))
diff -u --recursive --new-file v2.1.131/linux/drivers/pnp/parport_probe.c linux/drivers/pnp/parport_probe.c
--- v2.1.131/linux/drivers/pnp/parport_probe.c	Sun Nov  8 14:03:01 1998
+++ linux/drivers/pnp/parport_probe.c	Fri Dec 18 09:46:06 1998
@@ -54,8 +54,10 @@
 	unsigned int count = 0;
 	unsigned char z=0;
 	unsigned char Byte=0;
+	unsigned long igiveupat=jiffies+5*HZ;
 
-	for (i=0; ; i++) {
+	for (i=0; time_before(jiffies, igiveupat); i++) {
+	       /* if(current->need_resched) schedule(); */
 		parport_write_control(port, parport_read_control(port) | 2); /* AutoFeed high */
 		if (parport_wait_peripheral(port, 0x40, 0)) {
 #ifdef DEBUG_PROBE
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/Config.in linux/drivers/scsi/Config.in
--- v2.1.131/linux/drivers/scsi/Config.in	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/Config.in	Fri Dec 18 09:47:38 1998
@@ -19,6 +19,7 @@
 comment 'SCSI low-level drivers'
 
 dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
+dep_tristate 'ACARD SCSI support' CONFIG_SCSI_ACARD $CONFIG_SCSI
 dep_tristate 'Adaptec AHA152X/2825 support' CONFIG_SCSI_AHA152X $CONFIG_SCSI
 dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 $CONFIG_SCSI
 dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
@@ -34,19 +35,21 @@
 dep_tristate 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS $CONFIG_SCSI
 dep_tristate 'Always IN2000 SCSI support' CONFIG_SCSI_IN2000 $CONFIG_SCSI
 dep_tristate 'AM53/79C974 PCI SCSI support' CONFIG_SCSI_AM53C974 $CONFIG_SCSI
+dep_tristate 'AMI MegaRAID support' CONFIG_SCSI_MEGARAID $CONFIG_SCSI
+
 dep_tristate 'BusLogic SCSI support' CONFIG_SCSI_BUSLOGIC $CONFIG_SCSI
 if [ "$CONFIG_SCSI_BUSLOGIC" != "n" ]; then
     bool '  Omit FlashPoint support' CONFIG_SCSI_OMIT_FLASHPOINT
 fi
 dep_tristate 'DTC3180/3280 SCSI support' CONFIG_SCSI_DTC3280 $CONFIG_SCSI
-dep_tristate 'EATA-DMA (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
-dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
 dep_tristate 'EATA ISA/EISA/PCI (DPT and generic EATA/DMA-compliant boards) support' CONFIG_SCSI_EATA $CONFIG_SCSI
   if [ "$CONFIG_SCSI_EATA" != "n" ]; then
     bool '  enable tagged command queueing' CONFIG_SCSI_EATA_TAGGED_QUEUE
     bool '  enable elevator sorting' CONFIG_SCSI_EATA_LINKED_COMMANDS
     int  '  maximum number of queued commands' CONFIG_SCSI_EATA_MAX_TAGS 16
   fi
+dep_tristate 'EATA-DMA [Obsolete] (DPT, NEC, AT&T, SNI, AST, Olivetti, Alphatronix) support' CONFIG_SCSI_EATA_DMA $CONFIG_SCSI
+dep_tristate 'EATA-PIO (old DPT PM2001, PM2012A) support' CONFIG_SCSI_EATA_PIO $CONFIG_SCSI
 dep_tristate 'Future Domain 16xx SCSI/AHA 2920 support' CONFIG_SCSI_FUTURE_DOMAIN $CONFIG_SCSI
 if [ "$CONFIG_MCA" = "y" ]; then
   if [ "$CONFIG_SCSI" = "y" ]; then
@@ -68,6 +71,9 @@
 		"Port CONFIG_SCSI_G_NCR5380_PORT \
 		Memory CONFIG_SCSI_G_NCR5380_MEM" Port
 fi
+if [ "$CONFIG_PCI" = "y" ]; then
+  dep_tristate 'Initio 9100U(W) support' CONFIG_SCSI_INITIO $CONFIG_SCSI
+fi
 dep_tristate 'NCR53c406a SCSI support' CONFIG_SCSI_NCR53C406A $CONFIG_SCSI
 if [ "$CONFIG_PCI" = "y" ]; then
   dep_tristate 'NCR53c7,8xx SCSI support'  CONFIG_SCSI_NCR53C7xx $CONFIG_SCSI
@@ -100,6 +106,9 @@
      bool '  Reset SCSI-devices at boottime' CONFIG_IBMMCA_SCSI_DEV_RESET
   fi
 fi
+if [ "$CONFIG_MCA" = "y" ]; then
+  dep_tristate 'NCR MCA 53C9x SCSI support' CONFIG_SCSI_MCA_53C9X $CONFIG_SCSI
+fi
 dep_tristate 'PAS16 SCSI support' CONFIG_SCSI_PAS16 $CONFIG_SCSI
 dep_tristate 'PCI2000 support' CONFIG_SCSI_PCI2000 $CONFIG_SCSI
 dep_tristate 'PCI2220i support' CONFIG_SCSI_PCI2220I $CONFIG_SCSI
@@ -107,6 +116,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
 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.1.131/linux/drivers/scsi/Makefile linux/drivers/scsi/Makefile
--- v2.1.131/linux/drivers/scsi/Makefile	Thu Nov 12 16:21:20 1998
+++ linux/drivers/scsi/Makefile	Fri Dec 18 09:47:38 1998
@@ -195,6 +195,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_MCA_53C9X),y)
+L_OBJS += NCR53C9x.o mca_53c9x.o
+else
+  ifeq ($(CONFIG_SCSI_MCA_53C9X),m)
+  M_OBJS += NCR53C9x.o mca_53c9x.o
+  endif
+endif
+
 ifeq ($(CONFIG_CYBERSTORM_SCSI),y)
 L_OBJS += NCR53C9x.o cyberstorm.o
 else
@@ -276,6 +284,29 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_ACARD),y)
+L_OBJS += atp870u.o
+else
+  ifeq ($(CONFIG_SCSI_ACARD),m)
+  M_OBJS += atp870u.o
+  endif
+endif
+
+ifeq ($(CONFIG_SCSI_INITIO),y)
+L_OBJS += initio.o
+else
+  ifeq ($(CONFIG_SCSI_INITIO),m)
+  M_OBJS += initio.o
+  endif
+endif
+
+ifeq ($(CONFIG_SCSI_QLOGIC_FC),y)
+L_OBJS += qlogicfc.o 
+else
+  ifeq ($(CONFIG_SCSI_QLOGIC_FC),m)   
+  M_OBJS += qlogicfc.o 
+  endif
+endif
 
 ifeq ($(CONFIG_SCSI_AHA152X),y)
 L_OBJS += aha152x.o
@@ -539,6 +570,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_SCSI_MEGARAID),y)
+L_OBJS += megaraid.o
+else
+  ifeq ($(CONFIG_SCSI_MEGARAID),m)
+  M_OBJS += megaraid.o
+  endif
+endif
+
 ifeq ($(CONFIG_BLK_DEV_IDESCSI),y)
 L_OBJS += ide-scsi.o
 else
@@ -573,6 +612,15 @@
 
 53c7xx.o : 53c7xx_d.h 53c7xx.c
 	$(CC) $(CFLAGS) -c 53c7xx.c
+
+initio.o: ini9100u.c i91uscsi.c
+	$(CC) $(CFLAGS) -c ini9100u.c -o ini9100u.o
+	$(CC) $(CFLAGS) -c i91uscsi.c -o i91uscsi.o
+	$(LD) -r -o initio.o ini9100u.o i91uscsi.o
+	rm -f ini9100u.o i91uscsi.o
+
+megaraid.o: megaraid.c
+	$(CC) $(CFLAGS) -c megaraid.c
 
 scsi_mod.o: $(MIX_OBJS) hosts.o scsi.o scsi_ioctl.o constants.o \
 		scsicam.o scsi_proc.o scsi_error.o scsi_obsolete.o scsi_queue.o
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v2.1.131/linux/drivers/scsi/NCR5380.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/NCR5380.c	Fri Dec 18 09:47:38 1998
@@ -1919,7 +1919,7 @@
 		spin_lock_irq(&io_request_lock);
 		
 		if (time_after_eq(jiffies, timeout)) {
-			printk("scsi%d: timeout at NCR5380.c:%d\n", __LINE__);
+			printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);
 			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);
 			return -1;
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/NCR53C9x.c linux/drivers/scsi/NCR53C9x.c
--- v2.1.131/linux/drivers/scsi/NCR53C9x.c	Tue Jun 23 10:01:23 1998
+++ linux/drivers/scsi/NCR53C9x.c	Fri Dec 18 09:47:38 1998
@@ -6,6 +6,9 @@
  *
  * Most DMA dependencies put in driver specific files by 
  * Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Set up to use GETREG/SETREG (preprocessor macros in NCR53c9x.h) by
+ * Tymm Twillman (tymm@coe.missouri.edu)
  */
 
 /* TODO:
@@ -27,6 +30,7 @@
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
+
 #include <linux/init.h>
 
 #include "scsi.h"
@@ -297,7 +301,7 @@
 	esp->espcmdlog[esp->espcmdent] = cmd;
 	esp->espcmdent = (esp->espcmdent + 1) & 31;
 #endif
-	eregs->esp_cmd = cmd;
+	SETREG(eregs->esp_cmnd, cmd);
 }
 
 /* How we use the various Linux SCSI data structures for operation.
@@ -400,7 +404,7 @@
 	 */
 	esp->max_period = ((35 * esp->ccycle) / 1000);
 	if(esp->erev == fast) {
-		version = eregs->esp_uid;
+		version = GETREG(eregs->esp_uid);
 		family_code = (version & 0xf8) >> 3;
 #ifdef SYMBIOS_HACK
 		if (version == 0 && family_code == 0)
@@ -432,25 +436,25 @@
 	}
 
 	/* Reload the configuration registers */
-	eregs->esp_cfact = esp->cfact;
-	eregs->esp_stp   = 0;
-	eregs->esp_soff  = 0;
-	eregs->esp_timeo = esp->neg_defp;
+	SETREG(eregs->esp_cfact, esp->cfact);
+	SETREG(eregs->esp_stp, 0);
+	SETREG(eregs->esp_soff, 0);
+	SETREG(eregs->esp_timeo, esp->neg_defp);
 	esp->max_period = (esp->max_period + 3)>>2;
 	esp->min_period = (esp->min_period + 3)>>2;
 
-	eregs->esp_cfg1  = esp->config1;
+	SETREG(eregs->esp_cfg1, esp->config1);
 	switch(esp->erev) {
 	case esp100:
 		/* nothing to do */
 		break;
 	case esp100a:
-		eregs->esp_cfg2 = esp->config2;
+		SETREG(eregs->esp_cfg2, esp->config2);
 		break;
 	case esp236:
 		/* Slow 236 */
-		eregs->esp_cfg2 = esp->config2;
-		eregs->esp_cfg3 = esp->config3[0];
+		SETREG(eregs->esp_cfg2, esp->config2);
+		SETREG(eregs->esp_cfg3, esp->config3[0]);
 		break;
 	case fashme:
 		esp->config2 |= (ESP_CONFIG2_HME32 | ESP_CONFIG2_HMEFENAB);
@@ -458,7 +462,7 @@
 	case fas216:	    
 	case fas236:
 		/* Fast 236 or HME */
-		eregs->esp_cfg2 = esp->config2;
+		SETREG(eregs->esp_cfg2, esp->config2);
 		for(i=0; i<8; i++) {
 			if(esp->erev == fashme)
 				esp->config3[i] |=
@@ -466,7 +470,7 @@
 			else
 				esp->config3[i] |= ESP_CONFIG3_FCLK;
 		}
-		eregs->esp_cfg3 = esp->config3[0];
+		SETREG(eregs->esp_cfg3, esp->config3[0]);
 		if(esp->erev == fashme) {
 			esp->radelay = 80;
 		} else {
@@ -478,10 +482,10 @@
 		break;
 	case fas100a:
 		/* Fast 100a */
-		eregs->esp_cfg2 = esp->config2;
+		SETREG(eregs->esp_cfg2, esp->config2);
 		for(i=0; i<8; i++)
 			esp->config3[i] |= ESP_CONFIG3_FCLOCK;
-		eregs->esp_cfg3 = esp->config3[0];
+		SETREG(eregs->esp_cfg3, esp->config3[0]);
 		esp->radelay = 32;
 		break;
 	default:
@@ -490,7 +494,7 @@
 	};
 
 	/* Eat any bitrot in the chip */
-	trash = eregs->esp_intrpt;
+	trash = GETREG(eregs->esp_intrpt);
 	udelay(100);
 }
 
@@ -507,13 +511,13 @@
 	esp_reset_esp(esp, eregs);
 
 	/* Reset the SCSI bus, but tell ESP not to generate an irq */
-	eregs->esp_cfg1 |= ESP_CONFIG1_SRRDISAB;
+	SETREG(eregs->esp_cfg1, GETREG(eregs->esp_cfg1) | ESP_CONFIG1_SRRDISAB);
 	esp_cmd(esp, eregs, ESP_CMD_RS);
 	udelay(400);
-	eregs->esp_cfg1 = esp->config1;
+	SETREG(eregs->esp_cfg1, esp->config1);
 
 	/* Eat any bitrot in the chip and we are done... */
-	trash = eregs->esp_intrpt;
+	trash = GETREG(eregs->esp_intrpt);
 }
 
 /* Allocate structure and insert basic data such as SCSI chip frequency
@@ -650,19 +654,21 @@
 	/* Probe the revision of this esp */
 	esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
 	esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
-	eregs->esp_cfg2 = esp->config2;
+	SETREG(eregs->esp_cfg2, esp->config2);
 #ifndef SYMBIOS_HACK
-	if((eregs->esp_cfg2 & ~(ESP_CONFIG2_MAGIC)) !=
+	if((GETREG(eregs->esp_cfg2) & ~(ESP_CONFIG2_MAGIC)) !=
 	   (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
 		printk("NCR53C90(esp100) detected\n");
 		esp->erev = esp100;
 	} else {
 #endif
-		eregs->esp_cfg2 = esp->config2 = 0;
-		eregs->esp_cfg3 = 0;
-		eregs->esp_cfg3 = esp->config3[0] = 5;
+		esp->config2 = 0;
+		SETREG(eregs->esp_cfg2, esp->config2);
+		SETREG(eregs->esp_cfg3, 0);
+		esp->config3[0] = 5;
+		SETREG(eregs->esp_cfg3, esp->config3[0]);
 #ifndef SYMBIOS_HACK
-		if(eregs->esp_cfg3 != 5) {
+		if(GETREG(eregs->esp_cfg3) != 5) {
 			printk("NCR53C90A(esp100a) detected\n");
 			esp->erev = esp100a;
 		} else {
@@ -673,19 +679,21 @@
 			
 			for(target=0; target<8; target++)
 				esp->config3[target] = 0;
-			eregs->esp_cfg3 = 0;
+			SETREG(eregs->esp_cfg3, 0);
 #ifndef SYMBIOS_HACK
 			if(ccf > ESP_CCF_F5) {
 #endif
 				printk("NCR53C9XF(espfast) detected\n");
 				esp->erev = fast;
-				eregs->esp_cfg2 = esp->config2 = 0;
+				esp->config2 = 0;
+				SETREG(eregs->esp_cfg2, esp->config2);
 				esp->sync_defp = SYNC_DEFP_FAST;
 #ifndef SYMBIOS_HACK
 			} else {
 				printk("NCR53C9x(esp236) detected\n");
 				esp->erev = esp236;
-				eregs->esp_cfg2 = esp->config2 = 0;
+				esp->config2 = 0;
+				SETREG(eregs->esp_cfg2, esp->config2);
 			}
 		}
 #endif
@@ -1193,14 +1201,14 @@
 
 	/* HME sucks... */
 	if(esp->erev == fashme)
-		eregs->esp_busid = (target & 0xf) |
-			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+		SETREG(eregs->esp_busid, (target & 0xf) |
+			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
 	else
-		eregs->esp_busid = (target & 7);
-	eregs->esp_soff = SDptr->sync_max_offset;
-	eregs->esp_stp  = SDptr->sync_min_period;
+		SETREG(eregs->esp_busid, (target & 7));
+	SETREG(eregs->esp_soff, SDptr->sync_max_offset);
+	SETREG(eregs->esp_stp, SDptr->sync_min_period);
 	if(esp->erev > esp100a)
-		eregs->esp_cfg3 = esp->config3[target];
+		SETREG(eregs->esp_cfg3, esp->config3[target]);
 
 	i = (cmdp - esp->esp_command);
 
@@ -1209,7 +1217,7 @@
 		int j = 0;
 
 		for(;j<i;j++)
-			eregs->esp_fdata = esp->esp_command[j];
+			SETREG(eregs->esp_fdata, esp->esp_command[j]);
 		the_esp_command &= ~ESP_CMD_DMA;
 
 		/* Tell ESP to "go". */
@@ -1219,16 +1227,16 @@
 			esp_cmd(esp, eregs, ESP_CMD_FLUSH); /* Grrr! */
 
 			/* Set up the HME counters */
-			eregs->esp_tclow = i;
-			eregs->esp_tcmed = 0;
-			eregs->fas_rlo = 0;
-			eregs->fas_rhi = 0;
+			SETREG(eregs->esp_tclow, i);
+			SETREG(eregs->esp_tcmed, 0);
+			SETREG(eregs->fas_rlo, 0);
+			SETREG(eregs->fas_rhi, 0);
 			esp_cmd(esp, eregs, the_esp_command);
 			esp->dma_init_write(esp, esp->esp_command_dvma, 16);
 		} else {
 			/* Set up the ESP counters */
-			eregs->esp_tclow = i;
-			eregs->esp_tcmed = 0;
+			SETREG(eregs->esp_tclow, i);
+			SETREG(eregs->esp_tcmed, 0);
 			esp->dma_init_write(esp, esp->esp_command_dvma, i);
 
 			/* Tell ESP to "go". */
@@ -1341,7 +1349,8 @@
 	ESPLOG(("esp%d: SW [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
 		esp->esp_id, esp->sreg, esp->seqreg, esp->ireg));
 	ESPLOG(("esp%d: HW reread [sreg<%02x> sstep<%02x> ireg<%02x>]\n",
-		esp->esp_id, eregs->esp_status, eregs->esp_sstep, eregs->esp_intrpt));
+		esp->esp_id, GETREG(eregs->esp_status), 
+		GETREG(eregs->esp_sstep), GETREG(eregs->esp_intrpt)));
 #ifdef DEBUG_ESP_CMDS
 	printk("esp%d: last ESP cmds [", esp->esp_id);
 	i = (esp->espcmdent - 1) & 31;
@@ -1549,20 +1558,23 @@
 		return;
 	} else {
 		unsigned long count = 0;
-		unsigned long fcnt = eregs->esp_fflags & ESP_FF_FBYTES;
+		unsigned long fcnt = GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
 
 		/* The HME stores bytes in multiples of 2 in the fifo. */
 		ESPHME(("hme_fifo[fcnt=%d", (int)fcnt));
 		while(fcnt) {
-			esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
-			esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
+			esp->hme_fifo_workaround_buffer[count++] = 
+			 GETREG(eregs->esp_fdata);
+			esp->hme_fifo_workaround_buffer[count++] = 
+			 GETREG(eregs->esp_fdata);
 			ESPHME(("<%02x,%02x>", esp->hme_fifo_workaround_buffer[count-2], esp->hme_fifo_workaround_buffer[count-1]));
 			fcnt--;
 		}
-		if(eregs->esp_status2 & ESP_STAT2_F1BYTE) {
+		if(GETREG(eregs->esp_status2) & ESP_STAT2_F1BYTE) {
 			ESPHME(("<poke_byte>"));
-			eregs->esp_fdata = 0;
-			esp->hme_fifo_workaround_buffer[count++] = eregs->esp_fdata;
+			SETREG(eregs->esp_fdata, 0);
+			esp->hme_fifo_workaround_buffer[count++] = 
+			 GETREG(eregs->esp_fdata);
 			ESPHME(("<%02x,0x00>", esp->hme_fifo_workaround_buffer[count-1]));
 			ESPHME(("CMD_FLUSH"));
 			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
@@ -1579,8 +1591,8 @@
 {
 	esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 	while(count) {
-		eregs->esp_fdata = *bytes++;
-		eregs->esp_fdata = 0;
+		SETREG(eregs->esp_fdata, *bytes++);
+		SETREG(eregs->esp_fdata, 0);
 		count--;
 	}
 }
@@ -1596,7 +1608,7 @@
 
 	if(esp->dma_irq_p(esp)) {
 		/* Yes, we are able to save an interrupt. */
-		esp->sreg = eregs->esp_status;
+		esp->sreg = GETREG(eregs->esp_status);
 		if(esp->erev == fashme) {
 			/* This chip is really losing. */
 			ESPHME(("HME["));
@@ -1608,7 +1620,7 @@
 			ESPHME(("fifo_workaround]"));
 			hme_fifo_hwbug_workaround(esp, eregs);
 		}
-		esp->ireg = eregs->esp_intrpt;
+		esp->ireg = GETREG(eregs->esp_intrpt);
 		esp->sreg &= ~(ESP_STAT_INTR);
 		if(!(esp->ireg & ESP_INTR_SR))
 			return 0;
@@ -1630,7 +1642,7 @@
 		return 0;
 	if(esp->dma_irq_p(esp)) {
 		/* Yes, we are able to save an interrupt. */
-		esp->sreg = eregs->esp_status;
+		esp->sreg = GETREG(eregs->esp_status);
 		if(esp->erev == fashme) {
 			/* This chip is really losing. */
 			ESPHME(("HME["));
@@ -1643,7 +1655,7 @@
 			ESPHME(("fifo_workaround]"));
 			hme_fifo_hwbug_workaround(esp, eregs);
 		}
-		esp->ireg = eregs->esp_intrpt;
+		esp->ireg = GETREG(eregs->esp_intrpt);
 		esp->sreg &= ~(ESP_STAT_INTR);
 		if(!(esp->ireg & ESP_INTR_SR))
 			return 0;
@@ -1658,18 +1670,18 @@
 /* Misc. esp helper routines. */
 static inline void esp_setcount(struct ESP_regs *eregs, int cnt, int hme)
 {
-	eregs->esp_tclow = (cnt & 0xff);
-	eregs->esp_tcmed = ((cnt >> 8) & 0xff);
+	SETREG(eregs->esp_tclow, (cnt & 0xff));
+	SETREG(eregs->esp_tcmed, ((cnt >> 8) & 0xff));
 	if(hme) {
-		eregs->fas_rlo = 0;
-		eregs->fas_rhi = 0;
+		SETREG(eregs->fas_rlo, 0);
+		SETREG(eregs->fas_rhi, 0);
 	}
 }
 
 static inline int esp_getcount(struct ESP_regs *eregs)
 {
-	return (((eregs->esp_tclow)&0xff) |
-		(((eregs->esp_tcmed)&0xff) << 8));
+	return (((GETREG(eregs->esp_tclow))&0xff) |
+		(((GETREG(eregs->esp_tcmed))&0xff) << 8));
 }
 
 static inline int fcount(struct NCR_ESP *esp, struct ESP_regs *eregs)
@@ -1677,7 +1689,7 @@
 	if(esp->erev == fashme)
 		return esp->hme_fifo_workaround_count;
 	else
-		return eregs->esp_fflags & ESP_FF_FBYTES;
+		return GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
 }
 
 static inline int fnzero(struct NCR_ESP *esp, struct ESP_regs *eregs)
@@ -1685,7 +1697,7 @@
 	if(esp->erev == fashme)
 		return 0;
 	else
-		return eregs->esp_fflags & ESP_FF_ONOTZERO;
+		return GETREG(eregs->esp_fflags) & ESP_FF_ONOTZERO;
 }
 
 /* XXX speculative nops unnecessary when continuing amidst a data phase
@@ -1719,8 +1731,8 @@
 {
 	/* Do not touch this piece of code. */
 	if((!(esp->erev == esp100)) ||
-	   (!(sreg_datainp((esp->sreg = eregs->esp_status)) && !fifocnt) &&
-	    !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
+	   (!(sreg_datainp((esp->sreg = GETREG(eregs->esp_status))) && !fifocnt)
+	    && !(sreg_dataoutp(esp->sreg) && !fnzero(esp, eregs)))) {
 		if(sp->SCp.phase == in_dataout)
 			esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 		return 0;
@@ -1747,7 +1759,7 @@
 
 	if(esp->erev != esp100)
 		return 0;
-	junk = eregs->esp_intrpt;
+	junk = GETREG(eregs->esp_intrpt);
 
 	if(junk & ESP_INTR_SR)
 		return 1;
@@ -1772,7 +1784,7 @@
 		 */
 		targ = esp->hme_fifo_workaround_buffer[0];
 	} else {
-		it = eregs->esp_fdata;
+		it = GETREG(eregs->esp_fdata);
 		if(!(it & me))
 			return -1;
 		it &= ~me;
@@ -1796,7 +1808,7 @@
 	if(esp->erev == fashme)
 		lun = esp->hme_fifo_workaround_buffer[1];
 	else
-		lun = eregs->esp_fdata;
+		lun = GETREG(eregs->esp_fdata);
 	if(esp->sreg & ESP_STAT_PERR)
 		return 0;
 	if((lun & 0x40) || !(lun & 0x80))
@@ -1811,13 +1823,13 @@
 			       Scsi_Cmnd *sp)
 {
 	Scsi_Device *dp = sp->device;
-	eregs->esp_soff = dp->sync_max_offset;
-	eregs->esp_stp  = dp->sync_min_period;
+	SETREG(eregs->esp_soff, dp->sync_max_offset);
+	SETREG(eregs->esp_stp, dp->sync_min_period);
 	if(esp->erev > esp100a)
-		eregs->esp_cfg3 = esp->config3[sp->target];
+		SETREG(eregs->esp_cfg3, esp->config3[sp->target]);
 	if(esp->erev == fashme)
-		eregs->esp_busid = (sp->target & 0xf) |
-			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT);
+		SETREG(eregs->esp_busid, (sp->target & 0xf) |
+			(ESP_BUSID_RESELID | ESP_BUSID_CTR32BIT));
 	esp->current_SC = sp;
 }
 
@@ -1839,7 +1851,8 @@
 static inline int esp_do_msgin(struct NCR_ESP *esp, struct ESP_regs *eregs)
 {
 	/* Must be very careful with the fifo on the HME */
-	if((esp->erev != fashme) || !(eregs->esp_status2 & ESP_STAT2_FEMPTY))
+	if((esp->erev != fashme) || !(GETREG(eregs->esp_status2) & 
+	 ESP_STAT2_FEMPTY))
 		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 	esp_maybe_nop(esp, eregs);
 	esp_cmd(esp, eregs, ESP_CMD_TI);
@@ -1961,7 +1974,7 @@
 	 * will move and count 16-bit quantities during wide data.
 	 * SMCC _and_ Qlogic can both bite me.
 	 */
-	fifocnt = eregs->esp_fflags & ESP_FF_FBYTES;
+	fifocnt = GETREG(eregs->esp_fflags) & ESP_FF_FBYTES;
 	if(esp->erev != fashme)
 		ecount = esp_getcount(eregs);
 	bytes_sent = esp->current_transfer_size;
@@ -2360,16 +2373,18 @@
 			if(esp->do_pio_cmds){
 				esp_advance_phase(SCptr, in_status);
 				esp_cmd(esp, eregs, ESP_CMD_ICCSEQ);
-				while(!(esp->eregs->esp_status & ESP_STAT_INTR));
-				esp->esp_command[0] = eregs->esp_fdata;
-				while(!(esp->eregs->esp_status & ESP_STAT_INTR));
-				esp->esp_command[1] = eregs->esp_fdata;
+				while(!(GETREG(esp->eregs->esp_status)
+				 & ESP_STAT_INTR));
+				esp->esp_command[0] = GETREG(eregs->esp_fdata);
+				while(!(GETREG(esp->eregs->esp_status)
+				 & ESP_STAT_INTR));
+				esp->esp_command[1] = GETREG(eregs->esp_fdata);
 			} else {				
 				if(esp->erev != fashme) {
 					esp->esp_command[0] = 0xff;
 					esp->esp_command[1] = 0xff;
-					eregs->esp_tclow = 2;
-					eregs->esp_tcmed = 0;
+					SETREG(eregs->esp_tclow, 2);
+					SETREG(eregs->esp_tcmed, 0);
 					esp->dma_init_read(esp, esp->esp_command_dvma, 2);
 					esp_cmd(esp, eregs, ESP_CMD_DMA | ESP_CMD_ICCSEQ);
 				} else {
@@ -2456,11 +2471,11 @@
 	int cmd_bytes_sent, fcnt;
 
 	if(esp->erev != fashme)
-		esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS);
+		esp->seqreg = (GETREG(eregs->esp_sstep) & ESP_STEP_VBITS);
 	if(esp->erev == fashme)
 		fcnt = esp->hme_fifo_workaround_count;
 	else
-		fcnt = (eregs->esp_fflags & ESP_FF_FBYTES);
+		fcnt = (GETREG(eregs->esp_fflags) & ESP_FF_FBYTES);
 	cmd_bytes_sent = esp->dma_bytes_sent(esp, fcnt);
 	if(esp->dma_invalidate)
 		esp->dma_invalidate(esp);
@@ -2695,9 +2710,9 @@
 	esp_print_seqreg(esp->seqreg);
 	printk("\n");
 	printk("esp%d: New -- ", esp->esp_id);
-	esp->sreg = eregs->esp_status;
-	esp->seqreg = eregs->esp_sstep;
-	esp->ireg = eregs->esp_intrpt;
+	esp->sreg = GETREG(eregs->esp_status);
+	esp->seqreg = GETREG(eregs->esp_sstep);
+	esp->ireg = GETREG(eregs->esp_intrpt);
 	esp_print_ireg(esp->ireg);
 	printk(" ");
 	esp_print_statreg(esp->sreg);
@@ -2931,10 +2946,11 @@
 					esp->config3[SCptr->target] |= bit;
 				else
 					esp->config3[SCptr->target] &= ~bit;
-				eregs->esp_cfg3 = esp->config3[SCptr->target];
+				SETREG(eregs->esp_cfg3,
+				 esp->config3[SCptr->target]);
 			}
-			eregs->esp_soff = SDptr->sync_min_period;
-			eregs->esp_stp  = SDptr->sync_max_offset;
+			SETREG(eregs->esp_soff, SDptr->sync_min_period);
+			SETREG(eregs->esp_stp, SDptr->sync_max_offset);
 
 			ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n",
 				SDptr->sync_max_offset,
@@ -2949,15 +2965,16 @@
 			ESPSDTR(("unaccaptable sync nego, forcing async\n"));
 			SDptr->sync_max_offset = 0;
 			SDptr->sync_min_period = 0;
-			eregs->esp_soff = 0;
-			eregs->esp_stp = 0;
+			SETREG(eregs->esp_soff, 0);
+			SETREG(eregs->esp_stp, 0);
 			if((esp->erev == fas100a || esp->erev == fas216 || esp->erev == fas236 || esp->erev == fashme)) {
 				if((esp->erev == fas100a) || (esp->erev == fashme))
 					bit = ESP_CONFIG3_FAST;
 				else
 					bit = ESP_CONFIG3_FSCSI;
 				esp->config3[SCptr->target] &= ~bit;
-				eregs->esp_cfg3 = esp->config3[SCptr->target];
+				SETREG(eregs->esp_cfg3,
+				 esp->config3[SCptr->target]);
 			}
 		}
 
@@ -3007,7 +3024,7 @@
 				/* Pure paranoia. */
 				esp->config3[SCptr->target] &= ~(ESP_CONFIG3_EWIDE);
 			}
-			eregs->esp_cfg3 = esp->config3[SCptr->target];
+			SETREG(eregs->esp_cfg3, esp->config3[SCptr->target]);
 
 			/* Regardless, next try for sync transfers. */
 			build_sync_nego_msg(esp, esp->sync_defp, 15);
@@ -3038,7 +3055,8 @@
 				message_out = MSG_PARITY_ERROR;
 				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
 			} else if(esp->erev != fashme &&
-				  (it = (eregs->esp_fflags & ESP_FF_FBYTES))!=1) {
+				  (it = (GETREG(eregs->esp_fflags)
+				  & ESP_FF_FBYTES))!=1) {
 				/* We certainly dropped the ball somewhere. */
 				message_out = INITIATOR_ERROR;
 				esp_cmd(esp, eregs, ESP_CMD_FLUSH);
@@ -3046,7 +3064,7 @@
 				if(esp->erev == fashme)
 					it = esp->hme_fifo_workaround_buffer[0];
 				else
-					it = eregs->esp_fdata;
+					it = GETREG(eregs->esp_fdata);
 				esp_advance_phase(SCptr, in_msgincont);
 			} else {
 				/* it is ok and we want it */
@@ -3055,7 +3073,7 @@
 						esp->hme_fifo_workaround_buffer[0];
 				else
 					it = esp->cur_msgin[esp->msgin_ctr] =
-						eregs->esp_fdata;
+						GETREG(eregs->esp_fdata);
 				esp->msgin_ctr++;
 			}
 		} else {
@@ -3096,7 +3114,7 @@
 		esp_advance_phase(SCptr, in_the_dark);
 		esp->msgin_len = 0;
 	}
-	esp->sreg = eregs->esp_status;
+	esp->sreg = GETREG(eregs->esp_status);
 	esp->sreg &= ~(ESP_STAT_INTR);
 	if((esp->sreg & (ESP_STAT_PMSG|ESP_STAT_PCD)) == (ESP_STAT_PMSG|ESP_STAT_PCD))
 		esp_cmd(esp, eregs, ESP_CMD_MOK);
@@ -3123,7 +3141,7 @@
 		esp->dma_init_write(esp, esp->esp_command_dvma, i);
 	} else {
 		esp_cmd(esp, eregs, ESP_CMD_FLUSH);
-		eregs->esp_fdata = *esp->esp_scmdp++;
+		SETREG(eregs->esp_fdata, *esp->esp_scmdp++);
 		esp->esp_scmdleft--;
 		esp_cmd(esp, eregs, ESP_CMD_TI);
 	}
@@ -3154,14 +3172,14 @@
 		if(esp->erev == fashme)
 			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
 		else
-			eregs->esp_fdata = esp->cur_msgout[0];
+			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
 		esp_cmd(esp, eregs, ESP_CMD_TI);
 		break;
 
 	case 2:
 		if(esp->do_pio_cmds){
-			eregs->esp_fdata = esp->cur_msgout[0];
-			eregs->esp_fdata = esp->cur_msgout[1];
+			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
 			esp_cmd(esp, eregs, ESP_CMD_TI);
 		} else {
 			esp->esp_command[0] = esp->cur_msgout[0];
@@ -3180,10 +3198,10 @@
 	case 4:
 		esp->snip = 1;
 		if(esp->do_pio_cmds){
-			eregs->esp_fdata = esp->cur_msgout[0];
-			eregs->esp_fdata = esp->cur_msgout[1];
-			eregs->esp_fdata = esp->cur_msgout[2];
-			eregs->esp_fdata = esp->cur_msgout[3];
+			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[2]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[3]);
 			esp_cmd(esp, eregs, ESP_CMD_TI);
 		} else {
 			esp->esp_command[0] = esp->cur_msgout[0];
@@ -3204,18 +3222,18 @@
 	case 5:
 		esp->snip = 1;
 		if(esp->do_pio_cmds){
-			eregs->esp_fdata = esp->cur_msgout[0];
-			eregs->esp_fdata = esp->cur_msgout[1];
-			eregs->esp_fdata = esp->cur_msgout[2];
-			eregs->esp_fdata = esp->cur_msgout[3];
-			eregs->esp_fdata = esp->cur_msgout[4];
+			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[1]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[2]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[3]);
+			SETREG(eregs->esp_fdata, esp->cur_msgout[4]);
 			esp_cmd(esp, eregs, ESP_CMD_TI);
 		} else {
-			esp->esp_command[0] = esp->cur_msgout[0];
-			esp->esp_command[1] = esp->cur_msgout[1];
-			esp->esp_command[2] = esp->cur_msgout[2];
-			esp->esp_command[3] = esp->cur_msgout[3];
-			esp->esp_command[4] = esp->cur_msgout[4];
+			SETREG(esp->esp_command[0], esp->cur_msgout[0]);
+			SETREG(esp->esp_command[1], esp->cur_msgout[1]);
+			SETREG(esp->esp_command[2], esp->cur_msgout[2]);
+			SETREG(esp->esp_command[3], esp->cur_msgout[3]);
+			SETREG(esp->esp_command[4], esp->cur_msgout[4]);
 			if(esp->erev == fashme) {
 				hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 5);
 				esp_cmd(esp, eregs, ESP_CMD_TI);
@@ -3234,7 +3252,7 @@
 		if(esp->erev == fashme) {
 			hme_fifo_push(esp, eregs, &esp->cur_msgout[0], 1);
 		} else {
-			eregs->esp_fdata = esp->cur_msgout[0];
+			SETREG(eregs->esp_fdata, esp->cur_msgout[0]);
 		}
 		esp->msgout_len = 1;
 		esp_cmd(esp, eregs, ESP_CMD_TI);
@@ -3383,11 +3401,11 @@
 		esp->dma_irq_entry(esp);
 
 	/* Check for errors. */
-	esp->sreg = eregs->esp_status;
+	esp->sreg = GETREG(eregs->esp_status);
 	esp->sreg &= (~ESP_STAT_INTR);
 	if(esp->erev == fashme) {
-		esp->sreg2 = eregs->esp_status2;
-		esp->seqreg = (eregs->esp_sstep & ESP_STEP_VBITS);
+		esp->sreg2 = GETREG(eregs->esp_status2);
+		esp->seqreg = (GETREG(eregs->esp_sstep) & ESP_STEP_VBITS);
 	}
 	if(esp->sreg & (ESP_STAT_SPAM)) {
 		/* Gross error, could be due to one of:
@@ -3461,7 +3479,7 @@
 		}
 	}
 
-	esp->ireg = eregs->esp_intrpt;   /* Unlatch intr and stat regs */
+	esp->ireg = GETREG(eregs->esp_intrpt);   /* Unlatch intr and stat regs */
 
 	/* This cannot be done until this very moment. -DaveM */
 	synchronize_irq();
@@ -3674,7 +3692,7 @@
 }
 #else
 /* For SMP we only service one ESP on the list list at our IRQ level! */
-static void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+void esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
 {
 	struct NCR_ESP *esp;
 
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/NCR53C9x.h linux/drivers/scsi/NCR53C9x.h
--- v2.1.131/linux/drivers/scsi/NCR53C9x.h	Wed Jul  1 19:38:54 1998
+++ linux/drivers/scsi/NCR53C9x.h	Tue Dec 22 10:46:20 1998
@@ -1,4 +1,4 @@
-/* NCR53C9x.c:  Defines and structures for the NCR53C9x generic driver.
+/* NCR53C9x.h:  Defines and structures for the NCR53C9x generic driver.
  *
  * Originaly esp.h:  Defines and structures for the Sparc ESP 
  *                   (Enhanced SCSI Processor) driver under Linux.
@@ -6,6 +6,8 @@
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *
  * Generalization by Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * More generalization (for i386 stuff) by Tymm Twillman (tymm@computer.org)
  */
 
 #ifndef NCR53C9X_H
@@ -131,6 +133,15 @@
 /* All the ESP registers are one byte each and are accessed longwords
  * apart with a big-endian ordering to the bytes.
  */
+ 
+/*
+ * On intel, we must use inb() and outb() for register access, and the registers
+ *  are consecutive; no padding.
+ */ 
+
+#ifndef __i386__
+#define SETREG(reg, val) (reg = val)
+#define GETREG(reg)      (reg)
 
 struct ESP_regs {
                                 /* Access    Description              Offset */
@@ -140,7 +151,7 @@
                                 EREGS_PAD(fdpad);
     volatile unchar esp_fdata;  /* rw  FIFO data bits                 0x08   */
                                 EREGS_PAD(cbpad);
-    volatile unchar esp_cmd;    /* rw  SCSI command bits              0x0c   */
+    volatile unchar esp_cmnd;    /* rw  SCSI command bits              0x0c   */
                                 EREGS_PAD(stpad);
     volatile unchar esp_status; /* ro  ESP status register            0x10   */
 #define esp_busid   esp_status  /* wo  Bus ID for select/reselect     0x10   */
@@ -178,6 +189,52 @@
 #define fas_rhi     esp_fgrnd   /* rw  HME extended counter           0x3c  */
 };
 
+#else
+#define SETREG(reg, val) outb(val, reg)
+#define GETREG(reg)      inb(reg)
+
+struct ESP_regs {
+#ifdef CONFIG_MCA
+    unsigned int slot;
+#endif
+    unsigned int io_addr;
+                                  /* Access    Description              Offset */
+#define esp_tclow   io_addr      /* rw  Low bits of the transfer count 0x00   */
+#define esp_tcmed   io_addr + 1  /* rw  Mid bits of the transfer count 0x04   */
+#define esp_fdata   io_addr + 2  /* rw  FIFO data bits                 0x08   */
+#define esp_cmnd     io_addr + 3  /* rw  SCSI command bits              0x0c   */
+#define esp_status  io_addr + 4  /* ro  ESP status register            0x10   */
+#define esp_busid    esp_status   /* wo  Bus ID for select/reselect     0x10   */
+#define esp_intrpt  io_addr + 5  /* ro  Kind of interrupt              0x14   */
+#define esp_timeo    esp_intrpt   /* wo  Timeout value for select/resel 0x14   */
+#define esp_sstep   io_addr + 6  /* ro  Sequence step register         0x18   */
+#define esp_stp      esp_sstep    /* wo  Transfer period per sync       0x18   */
+#define esp_fflags  io_addr + 7  /* ro  Bits of current FIFO info      0x1c   */
+#define esp_soff     esp_fflags   /* wo  Sync offset                    0x1c   */
+#define esp_cfg1    io_addr + 8  /* rw  First configuration register   0x20   */
+#define esp_cfact   io_addr + 9  /* wo  Clock conversion factor        0x24   */
+#define esp_status2  esp_cfact    /* ro  HME status2 register           0x24   */
+#define esp_ctest   io_addr + 10 /* wo  Chip test register             0x28   */
+#define esp_cfg2    io_addr + 11 /* rw  Second configuration register  0x2c   */
+
+    /* The following is only found on the 53C9X series SCSI chips */
+#define esp_cfg3    io_addr + 12 /* rw  Third configuration register   0x30  */
+#define esp_hole    io_addr + 13 /* hole in register map               0x34  */
+
+    /* The following is found on all chips except the NCR53C90 (ESP100) */
+#define esp_tchi    io_addr + 14 /* rw  High bits of transfer count    0x38  */
+#define esp_uid      esp_tchi     /* ro  Unique ID code                 0x38  */
+#define fas_rlo      esp_tchi     /* rw  HME extended counter           0x38  */
+#define esp_fgrnd   io_addr + 15 /* rw  Data base for fifo             0x3c  */
+#define fas_rhi      esp_fgrnd    /* rw  HME extended counter           0x3c  */
+};
+
+#ifndef save_and_cli
+#define save_and_cli(flags)  save_flags(flags); cli();
+#endif
+
+#endif
+
 /* Various revisions of the ESP board. */
 enum esp_rev {
   esp100     = 0x00,  /* NCR53C90 - very broken */
@@ -195,7 +252,11 @@
 struct NCR_ESP {
   struct NCR_ESP *next;                   /* Next ESP on probed or NULL */
   struct ESP_regs *eregs;	          /* All esp registers */
+#ifndef __i386__
   struct Linux_DMA *dma;                  /* Who I do transfers with. */
+#else
+  int dma;
+#endif
   void *dregs;		  		  /* And his registers. */
   struct Scsi_Host *ehost;                /* Backpointer to SCSI Host */
 
@@ -272,6 +333,10 @@
   int scsi_id_mask;                       /* Bitmask of 'me'. */
   int diff;                               /* Differential SCSI bus? */
   int bursts;                             /* Burst sizes our DVMA supports */
+
+#ifdef CONFIG_MCA
+  int slot;				  /* MCA slot the adapter occupies */
+#endif
 
   /* Our command queues, only one cmd lives in the current_SC queue. */
   Scsi_Cmnd *issue_SC;           /* Commands to be issued */
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.1.131/linux/drivers/scsi/aic7xxx.c	Thu Nov 12 16:21:21 1998
+++ linux/drivers/scsi/aic7xxx.c	Fri Dec 18 09:47:38 1998
@@ -354,7 +354,7 @@
     0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
-#define AIC7XXX_C_VERSION  "5.1.4"
+#define AIC7XXX_C_VERSION  "5.1.6"
 
 #define NUMBER(arr)     (sizeof(arr) / sizeof(arr[0]))
 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
@@ -579,7 +579,8 @@
   "Adaptec AIC-7890/1 Ultra2 SCSI host adapter",        /* AIC_7890 */
   "Adaptec AHA-294X Ultra2 SCSI host adapter",          /* AIC_7890 */
   "Adaptec AIC-7896/7 Ultra2 SCSI host adapter",        /* AIC_7896 */
-  "Adaptec AHA-394X Ultra2 SCSI host adapter"           /* AIC_7897 */
+  "Adaptec AHA-394X Ultra2 SCSI host adapter",          /* AIC_7897 */
+  "Adaptec PCMCIA SCSI controller",                     /* card bus stuff */
 };
 
 /*
@@ -941,7 +942,6 @@
         struct aic7xxx_scb    *q_next;        /* next scb in queue */
         volatile scb_flag_type flags;         /* current state of scb */
         struct hw_scatterlist *sg_list;       /* SG list in adapter format */
-        void                  *kmalloc_ptr;
         unsigned char          tag_action;
         unsigned char          sg_count;
         unsigned char          sense_cmd[6];  /*
@@ -952,6 +952,7 @@
                                            * don't have to calculate anything
                                            * during underflow/overflow/stat code
                                            */
+        void                  *kmalloc_ptr;
 };
 
 /*
@@ -1029,84 +1030,68 @@
    *  This is the first 64 bytes in the host struct
    */
 
-  struct Scsi_Host        *host;             /* pointer to scsi host */
-  struct aic7xxx_host     *next;             /* allow for multiple IRQs */
-  int                      host_no;          /* SCSI host number */
-  unsigned long            base;             /* card base address */
-  volatile unsigned char  *maddr;            /* memory mapped address */
-  unsigned long            mbase;            /* I/O memory address */
+  /*
+   * We are grouping things here....first, items that get either read or
+   * written with nearly every interrupt
+   */
   volatile ahc_flag_type   flags;
-#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
-  spinlock_t               spin_lock;
-#endif
-  volatile unsigned char   cpu_lock_count[NR_CPUS];
-  ahc_chip                 chip;             /* chip type */
   ahc_feature              features;         /* chip features */
-  unsigned long            last_reset;
+  unsigned long            base;             /* card base address */
+  volatile unsigned char  *maddr;            /* memory mapped address */
   unsigned long            isr_count;        /* Interrupt count */
   unsigned long            spurious_int;
-  struct target_cmd       *targetcmds;
-  unsigned int             num_targetcmds;
+  scb_data_type           *scb_data;
+  struct aic7xxx_cmd_queue {
+    Scsi_Cmnd *head;
+    Scsi_Cmnd *tail;
+  } completeq;
+
+  /*
+   * Things read/written on nearly every entry into aic7xxx_queue()
+   */
+  volatile scb_queue_type  waiting_scbs;
   unsigned short           discenable;       /* Targets allowed to disconnect */
   unsigned short           tagenable;        /* Targets using tagged I/O */
   unsigned short           orderedtag;       /* Ordered Q tags allowed */
-  volatile unsigned char   activescbs;       /* active scbs */
-  volatile unsigned char   max_activescbs;
   unsigned char            unpause;          /* unpause value for HCNTRL */
   unsigned char            pause;            /* pause value for HCNTRL */
   volatile unsigned char   qoutfifonext;
+  volatile unsigned char   activescbs;       /* active scbs */
+  volatile unsigned char   max_activescbs;
   volatile unsigned char   qinfifonext;
 
-  /*
-   * MAX_TARGETS is currently == 16, so that makes these entries the next
-   * 64 bytes
-   */
-
 #define  DEVICE_PRESENT                 0x01
 #define  BUS_DEVICE_RESET_PENDING       0x02
-#define  DEVICE_TIMEOUT                 0x04
+#define  DEVICE_RESET_DELAY             0x04
 #define  DEVICE_PRINT_SDTR              0x08
 #define  DEVICE_PRINT_WDTR              0x10
-#define  DEVICE_SUCCESS                 0x20
-#define  DEVICE_TAGGED_SUCCESS          0x40
+#define  DEVICE_WAS_BUSY                0x20
 #define  DEVICE_SCANNED                 0x80
   volatile unsigned char   dev_flags[MAX_TARGETS];
   volatile unsigned char   dev_active_cmds[MAX_TARGETS];
   volatile unsigned char   dev_temp_queue_depth[MAX_TARGETS];
   unsigned char            dev_commands_sent[MAX_TARGETS];
 
-  /*
-   * The next 128 (or 256 on 64 bit machines)....
-   */
-  Scsi_Cmnd               *dev_wdtr_cmnd[MAX_TARGETS];
-  Scsi_Cmnd               *dev_sdtr_cmnd[MAX_TARGETS];
-
-  /*
-   * The next 64.... 
-   */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,1,0)
+  spinlock_t               spin_lock;
+  volatile unsigned char   cpu_lock_count[NR_CPUS];
+#endif
 
-  long                     dev_last_reset[MAX_TARGETS];
+  unsigned short           dev_timer_active; /* Which devs have a timer set */
 
-  /*
-   * The next 64....
-   */
+#ifdef AIC7XXX_FAKE_NEGOTIATION_CMDS
+  Scsi_Cmnd               *dev_wdtr_cmnd[MAX_TARGETS];
+  Scsi_Cmnd               *dev_sdtr_cmnd[MAX_TARGETS];
+#endif
 
-  unsigned char            dev_mid_level_queue_depth[MAX_TARGETS];
   unsigned char            dev_last_queue_full[MAX_TARGETS];
   unsigned char            dev_last_queue_full_count[MAX_TARGETS];
   unsigned char            dev_max_queue_depth[MAX_TARGETS];
 
-  /*
-   * The next 128....
-   */
-
   volatile scb_queue_type  delayed_scbs[MAX_TARGETS];
 
-  /*
-   *
-   */
-
-  struct timer_list        dev_timer[MAX_TARGETS];
+  unsigned long            dev_expires[MAX_TARGETS];
+  struct timer_list        dev_timer;
 
   /*
    * The next 64....
@@ -1120,16 +1105,6 @@
   unsigned char            msg_len;          /* Length of message */
   unsigned char            msg_index;        /* Index into msg_buf array */
   transinfo_type           transinfo[MAX_TARGETS];
-  volatile scb_queue_type  waiting_scbs;     /*
-                                              * SCBs waiting for space in
-                                              * the QINFIFO.
-                                              */
-  scb_data_type           *scb_data;
-
-  struct aic7xxx_cmd_queue {
-    Scsi_Cmnd *head;
-    Scsi_Cmnd *tail;
-  } completeq;
 
 
   /*
@@ -1170,6 +1145,12 @@
   struct seeprom_config    sc;
   unsigned short           sc_type;
   unsigned short           sc_size;
+  struct aic7xxx_host     *next;             /* allow for multiple IRQs */
+  struct Scsi_Host        *host;             /* pointer to scsi host */
+  int                      host_no;          /* SCSI host number */
+  unsigned long            mbase;            /* I/O memory address */
+  unsigned long            last_reset;
+  ahc_chip                 chip;             /* chip type */
 
   /*
    * Statistics Kept:
@@ -1189,16 +1170,22 @@
    * proc stats code is enabled.
    */
   struct aic7xxx_xferstats {
-    long xfers;                              /* total xfer count */
     long w_total;                            /* total writes */
-    long w_total512;                         /* 512 byte blocks written */
     long r_total;                            /* total reads */
-    long r_total512;                         /* 512 byte blocks read */
 #ifdef AIC7XXX_PROC_STATS
+    long xfers;                              /* total xfer count */
+    long w_total512;                         /* 512 byte blocks written */
+    long r_total512;                         /* 512 byte blocks read */
     long w_bins[10];                         /* binned write */
     long r_bins[10];                         /* binned reads */
 #endif /* AIC7XXX_PROC_STATS */
   } stats[MAX_TARGETS][MAX_LUNS];            /* [(channel << 3)|target][lun] */
+
+#if 0
+  struct target_cmd       *targetcmds;
+  unsigned int             num_targetcmds;
+#endif
+
 };
 
 /*
@@ -1282,11 +1269,9 @@
  */
 static int aic7xxx_reverse_scan = 0;
 /*
- * This setting enables a hack to fix the IRQ settings on buggy 7895
- * MB controller setups:
- *    -1 == Disable this hack
- *     0 == Use the Channel A IRQ for both channels
- *     1 == Use the Channel B IRQ for both channels
+ * Should we force EXTENDED translation on a controller.
+ *     0 == Use whatever is in the SEEPROM or default to off
+ *     1 == Use whatever is in the SEEPROM or default to on
  */
 static unsigned int aic7xxx_extended = 0;
 /*
@@ -1511,6 +1496,21 @@
   for(i=0; i<milliseconds; i++)
     udelay(1000);
 }
+
+static inline int
+time_after_eq(unsigned long a, unsigned long b)
+{
+  return((long)((a) - (b)) >= 0L);
+}
+
+static inline int
+timer_pending(struct timer_list *timer)
+{
+  return( timer->prev != NULL );
+}
+
+#define PCI_DEVICE_ID_ADAPTEC_1480A 0x6075
+
 #endif
 
 static inline unsigned char
@@ -1950,7 +1950,10 @@
   {
     printk(KERN_INFO "(scsi%d) Downloading sequencer code...", p->host_no);
   }
+#if 0
   download_consts[TMODE_NUMCMDS] = p->num_targetcmds;
+#endif
+  download_consts[TMODE_NUMCMDS] = 0;
   cur_patch = &sequencer_patches[0];
   downloaded = 0;
   skip_addr = 0;
@@ -2873,6 +2876,7 @@
     {
       char *buffer;
       
+      p->dev_flags[tindex] |= DEVICE_PRESENT;
       if(cmd->use_sg)
       {
         struct scatterlist *sg;
@@ -2914,23 +2918,34 @@
         p->needsdtr_copy |= (1<<tindex);
 
         if (p->flags & AHC_SEEPROM_FOUND)
+        {
           p->transinfo[tindex].goal_period = p->transinfo[tindex].user_period;
-        else if (p->features & AHC_ULTRA2)
-          p->transinfo[tindex].goal_period =
-            aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
-        else if (p->features & AHC_ULTRA)
-          p->transinfo[tindex].goal_period =
-            aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
-        else
-          p->transinfo[tindex].goal_period =
-            aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
-
-        if (p->features & AHC_ULTRA2)
-          p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
-        else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
-          p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+          p->transinfo[tindex].goal_offset = p->transinfo[tindex].user_offset;
+        }
         else
-          p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+        {
+          if (p->features & AHC_ULTRA2)
+          {
+            p->transinfo[tindex].goal_period =
+              aic7xxx_syncrates[AHC_SYNCRATE_ULTRA2].period;
+          }
+          else if (p->features & AHC_ULTRA)
+          {
+            p->transinfo[tindex].goal_period =
+              aic7xxx_syncrates[AHC_SYNCRATE_ULTRA].period;
+          }
+          else
+          {
+            p->transinfo[tindex].goal_period =
+              aic7xxx_syncrates[AHC_SYNCRATE_FAST].period;
+          }
+          if (p->features & AHC_ULTRA2)
+            p->transinfo[tindex].goal_offset = MAX_OFFSET_ULTRA2;
+          else if (p->transinfo[tindex].goal_width == MSG_EXT_WDTR_BUS_16_BIT)
+            p->transinfo[tindex].goal_offset = MAX_OFFSET_16BIT;
+          else
+            p->transinfo[tindex].goal_offset = MAX_OFFSET_8BIT;
+        }
       }
       else
       {
@@ -3077,11 +3092,6 @@
 #endif /* AIC7XXX_PROC_STATS */
 
       sp = &p->stats[TARGET_INDEX(cmd)][cmd->lun & 0x7];
-      sp->xfers++;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-      if ( (sp->xfers > 16) && (aic7xxx_verbose > 0xffff) )
-        aic7xxx_verbose &= 0xffff;
-#endif
 
       /*
        * For block devices, cmd->request.cmd is always == either READ or
@@ -3093,16 +3103,26 @@
            (cmd->data_cmnd[0] == WRITE_FILEMARKS) )
       {
         sp->w_total++;
-        sp->w_total512 += (actual >> 9);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
+        if ( (sp->w_total > 16) && (aic7xxx_verbose > 0xffff) )
+          aic7xxx_verbose &= 0xffff;
+#endif
 #ifdef AIC7XXX_PROC_STATS
+        sp->xfers++;
+        sp->w_total512 += (actual >> 9);
         ptr = sp->w_bins;
 #endif /* AIC7XXX_PROC_STATS */
       }
       else
       {
         sp->r_total++;
-        sp->r_total512 += (actual >> 9);
+#ifdef AIC7XXX_VERBOSE_DEBUGGING
+        if ( (sp->r_total > 16) && (aic7xxx_verbose > 0xffff) )
+          aic7xxx_verbose &= 0xffff;
+#endif
 #ifdef AIC7XXX_PROC_STATS
+        sp->xfers++;
+        sp->r_total512 += (actual >> 9);
         ptr = sp->r_bins;
 #endif /* AIC7XXX_PROC_STATS */
       }
@@ -3401,39 +3421,24 @@
 
     for (i = min_target; i <= max_target; i++)
     {
+      if ( i == p->scsi_id )
+      {
+        continue;
+      }
       if (aic7xxx_verbose & (VERBOSE_ABORT_PROCESS | VERBOSE_RESET_PROCESS))
         printk(INFO_LEAD "Cleaning up status information "
           "and delayed_scbs.\n", p->host_no, channel, i, lun);
-      if ( !(p->dev_flags[i] & DEVICE_TAGGED_SUCCESS) &&
-            (p->dev_active_cmds[i]) &&
-            (p->tagenable & (0x01 << i)) )
-      {
-        printk(INFO_LEAD "Device appears to be choking on tagged commands.\n",
-          p->host_no, channel, i, lun);
-        printk(INFO_LEAD "Will use untagged I/O instead.\n", p->host_no,
-          channel, i, lun);
-        p->dev_max_queue_depth[i] = 1;
-        p->dev_temp_queue_depth[i] = 1;
-        p->tagenable &= ~(0x01 << i);
-        p->orderedtag &= ~(0x01 << i);
-      }
       p->dev_flags[i] &= ~BUS_DEVICE_RESET_PENDING;
       if ( tag == SCB_LIST_NULL )
       {
-        p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR;
-        p->dev_last_reset[i] = jiffies;
+        p->dev_flags[i] |= DEVICE_PRINT_WDTR | DEVICE_PRINT_SDTR |
+                           DEVICE_RESET_DELAY;
+        p->dev_expires[i] = jiffies + (4 * HZ);
+        p->dev_timer_active |= (0x01 << i);
         p->dev_last_queue_full_count[i] = 0;
         p->dev_last_queue_full[i] = 0;
         p->dev_temp_queue_depth[i] =
           p->dev_max_queue_depth[i];
-  /*
-   * In case this isn't a full bus reset, we want to add a 4 second timer in
-   * here so that we can delay all re-sent commands for this device for the
-   * 4 seconds and then have our timer routine pick them back up.
-   */
-        del_timer(&p->dev_timer[i]);
-        p->dev_timer[i].expires = jiffies + (4 * HZ);
-        add_timer(&p->dev_timer[i]);
       }
       for(j=0; j<MAX_LUNS; j++)
       {
@@ -3480,8 +3485,14 @@
             "delayed_scbs queue!\n", p->host_no, channel, i, lun);
         scbq_init(&p->delayed_scbs[i]);
       }
-      if ( p->delayed_scbs[i].head == NULL )
-        del_timer(&p->dev_timer[i]);
+      if ( !(p->dev_timer_active & (0x01 << p->scsi_id)) ||
+            time_after_eq(p->dev_timer.expires, p->dev_expires[i]) )
+      {
+        del_timer(&p->dev_timer);
+        p->dev_timer.expires = p->dev_expires[i];
+        add_timer(&p->dev_timer);
+        p->dev_timer_active |= (0x01 << p->scsi_id);
+      }
     }
   }
 
@@ -3993,38 +4004,17 @@
     tindex = TARGET_INDEX(scb->cmd);
     if ( !scb->tag_action && (p->tagenable & (1<<tindex)) )
     {
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-      if (aic7xxx_verbose > 0xffff)
-        printk(INFO_LEAD "Reducing Queue depth for untagged command.\n",
-               p->host_no, CTL_OF_SCB(scb));
-#endif
       p->dev_temp_queue_depth[tindex] = 1;
     }
     if ( (p->dev_active_cmds[tindex] >=
           p->dev_temp_queue_depth[tindex]) ||
-         time_after_eq(p->dev_last_reset[tindex], jiffies - 4 * HZ) )
+         (p->dev_flags[tindex] & (DEVICE_RESET_DELAY|DEVICE_WAS_BUSY)) )
     {
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-      if (aic7xxx_verbose > 0xffff)
-        printk(INFO_LEAD "Moving SCB to Delayed Queue.\n",
-               p->host_no, CTL_OF_SCB(scb));
-#endif
       scbq_insert_tail(&p->delayed_scbs[tindex], scb);
-      if ( !timer_pending(&p->dev_timer[tindex]) &&
-           !(p->dev_active_cmds[tindex]) )
-      {
-        p->dev_timer[tindex].expires = p->dev_last_reset[tindex] + (4 * HZ);
-        add_timer(&p->dev_timer[tindex]);
-      }
     }
     else
     {
         scb->flags &= ~SCB_WAITINGQ;
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-        if (aic7xxx_verbose > 0xffff)
-          printk(INFO_LEAD "Sending command %d/0x%x to QINFIFO\n", p->host_no,
-                 CTL_OF_SCB(scb), scb->hscb->tag, scb->flags);
-#endif
         p->dev_active_cmds[tindex]++;
         p->activescbs++;
         if ( !(scb->tag_action) )
@@ -4037,16 +4027,6 @@
   }
   if (sent)
   {
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-    if (aic7xxx_verbose > 0xffff)
-    {
-      printk(INFO_LEAD "Sending commands to QINFIFO\n", p->host_no,
-             -1, -1, -1);
-      if ( (p->isr_count < 16) && (aic7xxx_panic_on_abort) &&
-           (p->flags & AHC_PAGESCBS) )
-        aic7xxx_check_scbs(p, "While sending commands to QINFIFO");
-    }
-#endif
     if (p->features & AHC_QUEUE_REGS)
       aic_outb(p, p->qinfifonext, HNSCB_QOFF);
     else
@@ -4147,12 +4127,18 @@
 #else
   spin_lock_irqsave(&io_request_lock, cpu_flags);
 #endif
+  p->dev_timer_active &= ~(0x01 << p->scsi_id);
   for(i=0; i<MAX_TARGETS; i++)
   {
-    if ( timer_pending(&p->dev_timer[i]) && 
-         time_before_eq(p->dev_timer[i].expires, jiffies) )
+    if ( i == p->scsi_id )
+    {
+      continue;
+    }
+    if ( (p->dev_timer_active & (0x01 << i)) &&
+         time_after_eq(jiffies, p->dev_expires[i]) )
     {
-      del_timer(&p->dev_timer[i]);
+      p->dev_timer_active &= ~(0x01 << i);
+      p->dev_flags[i] &= ~(DEVICE_RESET_DELAY|DEVICE_WAS_BUSY);
       p->dev_temp_queue_depth[i] =  p->dev_max_queue_depth[i];
       j = 0;
       while ( ((scb = scbq_remove_head(&p->delayed_scbs[i])) != NULL) &&
@@ -4172,7 +4158,27 @@
          */
       }
     }
+    else if ( p->dev_timer_active & (0x01 << i) )
+    {
+      if ( p->dev_timer_active & (0x01 << p->scsi_id) )
+      {
+        if ( time_after_eq(p->dev_timer.expires, p->dev_expires[i]) )
+        {
+          p->dev_timer.expires = p->dev_expires[i];
+        }
+      }
+      else
+      {
+        p->dev_timer.expires = p->dev_expires[i];
+        p->dev_timer_active |= (0x01 << p->scsi_id);
+      }
+    }
   }
+  if ( p->dev_timer_active & (0x01 << p->scsi_id) )
+  {
+    add_timer(&p->dev_timer);
+  }
+
   aic7xxx_run_waiting_queues(p);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,95)   
   DRIVER_UNLOCK
@@ -4447,8 +4453,7 @@
              (scb->tag_action) &&
             !(scb->flags & SCB_MSGOUT_BITS) )
         {
-          if ((scb->tag_action == MSG_ORDERED_Q_TAG) &&
-              (p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS))
+          if (scb->tag_action == MSG_ORDERED_Q_TAG)
           {
             /*
              * OK...the device seems able to accept tagged commands, but
@@ -4469,8 +4474,7 @@
             aic_outb(p, MSG_IDENTIFYFLAG, MSG_OUT);
             aic_outb(p, aic_inb(p, SCSISIGI) | ATNO, SCSISIGO);
           }
-          else if ( (scb->tag_action == MSG_SIMPLE_Q_TAG) &&
-                   !(p->dev_flags[tindex] & DEVICE_TAGGED_SUCCESS) )
+          else if (scb->tag_action == MSG_SIMPLE_Q_TAG)
           {
             unsigned char i, reset = 0;
             struct aic7xxx_scb *scbp;
@@ -4885,17 +4889,29 @@
               p->activescbs--;
               scb->flags |= SCB_WAITINGQ | SCB_WAS_BUSY;
                   
-              if ( !timer_pending(&p->dev_timer[tindex]) ) 
+              if ( !(p->dev_timer_active & (0x01 << tindex)) ) 
               {
+                p->dev_timer_active |= (0x01 << tindex);
                 if ( p->dev_active_cmds[tindex] )
                 {
-                  p->dev_timer[tindex].expires = jiffies + (HZ * 2);
-                  add_timer(&p->dev_timer[tindex]);
+                  p->dev_expires[tindex] = jiffies + HZ;
                 }
                 else
                 {
-                  p->dev_timer[tindex].expires = jiffies + (HZ / 2);
-                  add_timer(&p->dev_timer[tindex]);
+                  p->dev_expires[tindex] = jiffies + (HZ / 10);
+                }
+                if ( !(p->dev_timer_active & (0x01 << p->scsi_id)) )
+                {
+                  p->dev_timer.expires = p->dev_expires[tindex];
+                  p->dev_timer_active |= (0x01 << p->scsi_id);
+                  add_timer(&p->dev_timer);
+                }
+                else if ( time_after_eq(p->dev_timer.expires,
+                                        p->dev_expires[tindex]) )
+                {
+                  del_timer(&p->dev_timer);
+                  p->dev_timer.expires = p->dev_expires[tindex];
+                  add_timer(&p->dev_timer);
                 }
               }
 #ifdef AIC7XXX_VERBOSE_DEBUGGING
@@ -4937,6 +4953,10 @@
                   p->dev_last_queue_full[tindex] = 0;
                   p->dev_last_queue_full_count[tindex] = 0;
                 }
+                else
+                {
+                  p->dev_flags[tindex] |= DEVICE_WAS_BUSY;
+                }
               }
               break;
             }
@@ -5255,50 +5275,61 @@
         {
           maxsync = AHC_SYNCRATE_FAST;
         }
-  
-#ifdef AIC7XXX_VERBOSE_DEBUGGING
-        if (aic7xxx_verbose > 0xffff)
-        {
-          printk(INFO_LEAD "Finished receipt of SDTR, parsing %d/%d\n",
-                 p->host_no, CTL_OF_SCB(scb), period, offset);
-          syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
-          printk(INFO_LEAD "After find_syncrate() %d/%d\n",
-                 p->host_no, CTL_OF_SCB(scb), period, offset);
-          aic7xxx_validate_offset(p, syncrate, &offset,
-                                  target_scsirate & WIDEXFER);
-          printk(INFO_LEAD "After validate_offset() %d/%d\n",
-                 p->host_no, CTL_OF_SCB(scb), period, offset);
-          aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                               offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-          printk(INFO_LEAD "Final values of Period/Offset as set: %d/%d\n",
-                 p->host_no, CTL_OF_SCB(scb), period, offset);
-        }
-        else
+        /*
+         * We might have a device that is starting negotiation with us
+         * before we can start up negotiation with it....be prepared to
+         * have a device ask for a higher speed then we want to give it
+         * in that case
+         */
+        if ( (scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+             (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) )
         {
-          syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
-          aic7xxx_validate_offset(p, syncrate, &offset,
-                                  target_scsirate & WIDEXFER);
-          aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                               offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
+          if (!(p->dev_flags[tindex] & DEVICE_SCANNED))
+          {
+            /*
+             * Not only is the device starting this up, but it also hasn't
+             * been scanned yet, so this would likely be our TUR or our
+             * INQUIRY command at scan time, so we need to use the
+             * settings from the SEEPROM if they existed.  Of course, even
+             * if we didn't find a SEEPROM, we stuffed default values into
+             * the user settings anyway, so use those in all cases.
+             */
+            p->transinfo[tindex].goal_period =
+              p->transinfo[tindex].user_period;
+            p->transinfo[tindex].goal_offset =
+              p->transinfo[tindex].user_offset;
+            p->needsdtr_copy |= target_mask;
+          }
+          if ( !p->transinfo[tindex].goal_offset )
+            period = 255;
+          if ( p->transinfo[tindex].goal_period > period )
+            period = p->transinfo[tindex].goal_period;
         }
-#else
+  
         syncrate = aic7xxx_find_syncrate(p, &period, maxsync);
         aic7xxx_validate_offset(p, syncrate, &offset,
                                 target_scsirate & WIDEXFER);
         aic7xxx_set_syncrate(p, syncrate, target, channel, period,
                              offset, AHC_TRANS_ACTIVE|AHC_TRANS_CUR);
-#endif
 
-        if (offset == 0)
+        /*
+         * Did we drop to async?  If so, are we sending a reply?  If we are,
+         * then we have to make sure that the reply value reflects the proper
+         * settings so we need to set the goal values according to what
+         * we need to send.
+         */
+        if ( (offset == 0) || (offset != saved_offset) ||
+             ((scb->flags & (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR)) !=
+              (SCB_MSGOUT_SENT|SCB_MSGOUT_SDTR) ) )
         {
-          /*
-           * Uhh ohh, things fell through to async....update the goal
-           * items and the needsdtr_copy to reflect this...
-           */
           aic7xxx_set_syncrate(p, syncrate, target, channel, period,
-                 offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
-          p->needsdtr_copy &= ~target_mask;
+                               offset, AHC_TRANS_GOAL|AHC_TRANS_QUITE);
+          if ( offset == 0 )
+          {
+            p->needsdtr_copy &= ~target_mask;
+          }
         }
+        
         /*
          * Did we start this, if not, or if we went to low and had to
          * go async, then send an SDTR back to the target
@@ -5313,32 +5344,6 @@
         }
         else
         {
-          /*
-           * Send a reply SDTR back.  Even if we sent the first one, it
-           * is valid to send another one out immediately to re-negotiate
-           * things, and a few devices don't like getting rejects after
-           * we already sent them one SDTR.  Just send an SDTR for async
-           * this time if need be (or for the correct params if we didn't
-           * start all of this).  If this is a Reject Reply type message,
-           * then we've put the async settings into the goal area for
-           * future reference (when we get the AWAITING_MSG interrupt).
-           * If this is a case where we are responding to the target's
-           * initiated SDTR, then leave our own goal and user values in
-           * place (unless the device hasn't been scanned yet, in which
-           * case, put the user values into the goal values so we don't
-           * send out an Async message).
-           */
-          if ( !(p->dev_flags[tindex] & DEVICE_SCANNED) )
-          {
-            p->transinfo[tindex].goal_width =
-              p->transinfo[tindex].user_width;
-            p->transinfo[tindex].goal_period =
-              p->transinfo[tindex].user_period;
-            p->transinfo[tindex].goal_offset =
-              p->transinfo[tindex].user_offset;
-            p->needwdtr_copy |= target_mask;
-            p->needsdtr_copy |= target_mask;
-          }
           scb->flags &= ~SCB_MSGOUT_BITS;
           scb->flags |= SCB_MSGOUT_SDTR;
           aic_outb(p, HOST_MSG, MSG_OUT);
@@ -5407,12 +5412,12 @@
              * it contacted us first, mark it as such and copy the user stuff
              * over to the goal stuff.
              */
-            p->transinfo[tindex].goal_width =
-              p->transinfo[tindex].user_width;
             p->transinfo[tindex].goal_period =
               p->transinfo[tindex].user_period;
             p->transinfo[tindex].goal_offset =
               p->transinfo[tindex].user_offset;
+            p->transinfo[tindex].goal_width =
+              p->transinfo[tindex].user_width;
             p->needwdtr_copy |= target_mask;
             p->needsdtr_copy |= target_mask;
           }
@@ -5432,6 +5437,8 @@
             {
               p->needwdtr_copy &= ~target_mask;
               bus_width = MSG_EXT_WDTR_BUS_8_BIT;
+              aic7xxx_set_width(p, target, channel, lun, bus_width,
+                                AHC_TRANS_GOAL|AHC_TRANS_QUITE);
               break;
             }
           }
@@ -6241,12 +6248,6 @@
             aic7xxx_calculate_residual(p, scb);
           }
           cmd->result |= (aic7xxx_error(cmd) << 16);
-          if (scb->tag_action)
-            p->dev_flags[TARGET_INDEX(cmd)] |= 
-               DEVICE_TAGGED_SUCCESS | DEVICE_SUCCESS | DEVICE_PRESENT;
-          else
-            p->dev_flags[TARGET_INDEX(cmd)] |= 
-               DEVICE_SUCCESS | DEVICE_PRESENT;
           aic7xxx_done(p, scb);
           break;
       }      
@@ -6392,7 +6393,6 @@
   target_mask = (1 << tindex);
 
   device->queue_depth = default_depth;
-  p->dev_mid_level_queue_depth[tindex] = 3;
   p->dev_temp_queue_depth[tindex] = 1;
   p->dev_max_queue_depth[tindex] = 1;
   p->tagenable &= ~target_mask;
@@ -6457,7 +6457,6 @@
         }
         p->dev_max_queue_depth[tindex] = device->queue_depth;
         p->dev_temp_queue_depth[tindex] = device->queue_depth;
-        p->dev_mid_level_queue_depth[tindex] = device->queue_depth;
         p->tagenable |= target_mask;
         p->orderedtag |= target_mask;
         device->tagged_queue = 1;
@@ -7461,6 +7460,10 @@
   p->completeq.tail = NULL;
   scbq_init(&p->scb_data->free_scbs);
   scbq_init(&p->waiting_scbs);
+  init_timer(&p->dev_timer);
+  p->dev_timer.data = (unsigned long)p;
+  p->dev_timer.function = (void *)aic7xxx_timer;
+  p->dev_timer_active = 0;
 
   for (i = 0; i < NUMBER(p->untagged_scbs); i++)
   {
@@ -7479,16 +7482,12 @@
     p->dev_commands_sent[i] = 0;
     p->dev_flags[i] = 0;
     p->dev_active_cmds[i] = 0;
-    p->dev_last_reset[i] = jiffies;
     p->dev_last_queue_full[i] = 0;
     p->dev_last_queue_full_count[i] = 0;
     p->dev_max_queue_depth[i] = 1;
     p->dev_temp_queue_depth[i] = 1;
-    p->dev_mid_level_queue_depth[i] = 3;
+    p->dev_expires[i] = 0;
     scbq_init(&p->delayed_scbs[i]);
-    init_timer(&p->dev_timer[i]);
-    p->dev_timer[i].data = (unsigned long)p;
-    p->dev_timer[i].function = (void *)aic7xxx_timer;
   }
 
   printk(KERN_INFO "(scsi%d) <%s> found at ", p->host_no,
@@ -8156,6 +8155,21 @@
           have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
                                       scarray, p->sc_size, C46);
       }
+      if (!have_seeprom)
+      {
+        p->sc_size = 128;
+        have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+                                    scarray, p->sc_size, p->sc_type);
+        if (!have_seeprom)
+        {
+          if(p->sc_type == C46)
+            have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+                                        scarray, p->sc_size, C56_66);
+          else
+            have_seeprom = read_seeprom(p, (p->flags & (AHC_CHNLB|AHC_CHNLC)),
+                                        scarray, p->sc_size, C46);
+        }
+      }
       break;
   }
 
@@ -8187,7 +8201,8 @@
       sc->adapter_control &= ~CFAUTOTERM;
       sc->adapter_control |= CFSTERM | CFWSTERM | CFLVDSTERM;
     }
-    p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
+    if (aic7xxx_extended)
+      p->flags |= AHC_EXTEND_TRANS_A | AHC_EXTEND_TRANS_B;
   }
   else
   {
@@ -8341,7 +8356,8 @@
       }
       else if (sc->device_flags[i] & CFNEWULTRAFORMAT)
       {
-        if ( (sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03 )
+        if ( ((sc->device_flags[i] & (CFSYNCHISULTRA | CFXFER)) == 0x03) &&
+             !(p->features & AHC_ULTRA2) )
         {
           sc->device_flags[i] &= ~CFXFER;
           sc->device_flags[i] |= CFSYNCHISULTRA;
@@ -8622,12 +8638,6 @@
         current_p = current_p->next;
       current_p->next = temp_p;
     }
-    if (aic7xxx_extended)
-    {
-      temp_p->flags |= AHC_EXTEND_TRANS_A;
-      if (temp_p->flags & AHC_MULTI_CHANNEL)
-        temp_p->flags |= AHC_EXTEND_TRANS_B;
-    }
 
     switch (type)
     {
@@ -8846,6 +8856,10 @@
        AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED | AHC_MULTI_CHANNEL,
        AHC_AIC7896_FE,                                      23,
        32, C56_66 },
+      {PCI_VENDOR_ID_ADAPTEC, PCI_DEVICE_ID_ADAPTEC_1480A, AHC_AIC7860,
+       AHC_PAGESCBS | AHC_NEWEEPROM_FMT | AHC_BIOS_ENABLED,
+       AHC_AIC7860_FE,                                      24,
+       32, C46 },
     };
 
     unsigned short command;
@@ -9327,9 +9341,6 @@
             aic_outb(temp_p, DFTHRSH_100, DSPCISTATUS);
           }
 
-          if (aic7xxx_extended)
-            temp_p->flags |= AHC_EXTEND_TRANS_A;
-
           if ( list_p == NULL )
           {
             list_p = current_p = temp_p;
@@ -10096,8 +10107,6 @@
                 "message buffer\n", p->host_no, CTL_OF_SCB(scb));
         scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
         aic7xxx_error(scb->cmd) = DID_RESET;
-        p->dev_flags[TARGET_INDEX(scb->cmd)] &= 
-                ~DEVICE_SUCCESS;
         p->dev_flags[TARGET_INDEX(scb->cmd)] |= 
                 BUS_DEVICE_RESET_PENDING;
         /* Send the abort message to the active SCB. */
@@ -10118,8 +10127,6 @@
                 "in use\n", p->host_no, CTL_OF_SCB(scb));
         scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
         aic7xxx_error(scb->cmd) = DID_RESET;
-        p->dev_flags[TARGET_INDEX(scb->cmd)] &= 
-                ~DEVICE_SUCCESS;
         p->dev_flags[TARGET_INDEX(scb->cmd)] |= 
                 BUS_DEVICE_RESET_PENDING;
         return(SCSI_RESET_ERROR);
@@ -10147,7 +10154,6 @@
          */
     scb->hscb->control |= MK_MESSAGE;
     scb->flags |= SCB_RESET | SCB_DEVICE_RESET;
-    p->dev_flags[TARGET_INDEX(scb->cmd)] &= ~DEVICE_SUCCESS;
     p->dev_flags[TARGET_INDEX(scb->cmd)] |= 
         BUS_DEVICE_RESET_PENDING;
     if (hscb_index != SCB_LIST_NULL)
@@ -10227,7 +10233,7 @@
     {
       mask = (0x01 << i);
       printk(INFO_LEAD "dev_flags=0x%x, WDTR:%c/%c/%c, SDTR:%c/%c/%c,"
-             " q_depth=%d:%d:%d\n",
+             " q_depth=%d:%d\n",
         p->host_no, 0, i, 0, p->dev_flags[i],
         (p->wdtr_pending & mask) ? 'Y' : 'N',
         (p->needwdtr & mask) ? 'Y' : 'N',
@@ -10236,7 +10242,7 @@
         (p->needsdtr & mask) ? 'Y' : 'N',
         (p->needsdtr_copy & mask) ? 'Y' : 'N',
         p->dev_active_cmds[i],
-        p->dev_max_queue_depth[i], p->dev_mid_level_queue_depth[i]);
+        p->dev_max_queue_depth[i] );
       printk(INFO_LEAD "targ_scsirate=0x%x", p->host_no, 0, i, 0,
              aic_inb(p, TARG_SCSIRATE + i));
       if (p->features & AHC_ULTRA2)
@@ -10877,7 +10883,7 @@
   {
     action = HOST_RESET;
   }
-  if ( ((jiffies - p->dev_last_reset[tindex]) < (HZ * 3)) &&
+  if ( (p->dev_flags[tindex] & DEVICE_RESET_DELAY) &&
        !(action & (HOST_RESET | BUS_RESET)))
   {
     if (aic7xxx_verbose & VERBOSE_RESET_PROCESS)
@@ -10960,9 +10966,25 @@
         p->msg_len = 0;
       }
       aic7xxx_run_done_queue(p, TRUE);
+      /*
+       * If this a SCSI_RESET_SYNCHRONOUS then the command we were given is
+       * in need of being re-started, so send it on through to aic7xxx_queue
+       * and let it set until the delay is over.  This keeps it from dying
+       * entirely and avoids getting a bogus dead command back through the
+       * mid-level code due to too many retries.
+       */
+      if ( flags & SCSI_RESET_SYNCHRONOUS )
+      {
+        cmd->result = DID_RESET << 16;
+        cmd->done(cmd);
+      }
       p->flags &= ~AHC_IN_RESET;
-      /*  We can't rely on run_waiting_queues to unpause the sequencer for
-       *  PCI based controllers since we use AAP */
+      /*
+       * We can't rely on run_waiting_queues to unpause the sequencer for
+       * PCI based controllers since we use AAP.  NOTE: this also sets
+       * the timer for the one command we might have queued in the case
+       * of a synch reset.
+       */
       aic7xxx_run_waiting_queues(p);
       unpause_sequencer(p, FALSE);
       DRIVER_UNLOCK
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/aic7xxx_proc.c linux/drivers/scsi/aic7xxx_proc.c
--- v2.1.131/linux/drivers/scsi/aic7xxx_proc.c	Fri Oct  9 13:27:10 1998
+++ linux/drivers/scsi/aic7xxx_proc.c	Fri Dec 18 09:47:38 1998
@@ -132,7 +132,7 @@
   {
     for (lun = 0; lun < MAX_LUNS; lun++)
     {
-      if (p->stats[target][lun].xfers != 0)
+      if (p->stats[target][lun].r_total != 0)
 #ifdef AIC7XXX_PROC_STATS
         size += 512;
 #else
@@ -278,7 +278,7 @@
     for (lun = 0; lun < MAX_LUNS; lun++)
     {
       sp = &p->stats[target][lun];
-      if (sp->xfers == 0)
+      if (sp->r_total == 0)
       {
         continue;
       }
@@ -331,11 +331,11 @@
                       p->transinfo[target].cur_period,
                       p->transinfo[target].cur_offset,
                       p->transinfo[target].cur_width);
+#ifdef AIC7XXX_PROC_STATS
       size += sprintf(BLS, "    Total transfers %ld (%ld read;%ld written)\n",
           sp->xfers, sp->r_total, sp->w_total);
       size += sprintf(BLS, "      blks(512) rd=%ld; blks(512) wr=%ld\n",
           sp->r_total512, sp->w_total512);
-#ifdef AIC7XXX_PROC_STATS
       size += sprintf(BLS, "%s\n", HDRB);
       size += sprintf(BLS, " Reads:");
       for (i = 0; i < NUMBER(sp->r_bins); i++)
@@ -348,6 +348,9 @@
       {
         size += sprintf(BLS, "%6ld ", sp->w_bins[i]);
       }
+#else
+      size += sprintf(BLS, "    Total transfers: %ld/%ld read/written)\n",
+          sp->r_total, sp->w_total);
 #endif /* AIC7XXX_PROC_STATS */
       size += sprintf(BLS, "\n\n");
     }
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/atp870u.c linux/drivers/scsi/atp870u.c
--- v2.1.131/linux/drivers/scsi/atp870u.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/atp870u.c	Fri Dec 18 09:48:05 1998
@@ -0,0 +1,2037 @@
+/* $Id: atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $
+ *  linux/kernel/atp870u.c
+ *
+ *  Copyright (C) 1997	Wu Ching Chen
+ *  2.1.x update (C) 1998  Krzysztof G. Baranowski
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/pci.h>
+#include <linux/blk.h>
+#include "scsi.h"
+#include "hosts.h"
+
+
+#include "atp870u.h"
+
+#include<linux/stat.h>
+
+struct proc_dir_entry proc_scsi_atp870u = {
+    PROC_SCSI_ATP870U, 7, "atp870u",
+    S_IFDIR | S_IRUGO | S_IXUGO, 2
+};
+
+void mydlyu(unsigned int);
+/*
+static const char RCSid[] = "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/atp870u.c,v 1.0 1997/05/07 15:22:00 root Exp root $";
+*/
+
+static unsigned char admaxu=1,host_idu[2],chip_veru[2],scam_on[2],global_map[2];
+static unsigned short int active_idu[2],wide_idu[2],sync_idu,ultra_map[2];
+static int  workingu[2]={0,0};
+static Scsi_Cmnd *querequ[2][qcnt],*curr_req[2][16];
+static unsigned char devspu[2][16] = {{0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+				0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20},
+			       {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
+				0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20}};
+static unsigned char dirctu[2][16],last_cmd[2],in_snd[2],in_int[2];
+static unsigned char ata_cdbu[2][16];
+static unsigned int ioportu[2]={0,0};
+static unsigned int irqnumu[2]={0,0};
+static unsigned short int pciportu[2];
+static unsigned long prdaddru[2][16],tran_lenu[2][16],last_lenu[2][16];
+static unsigned char prd_tableu[2][16][1024];
+static unsigned char *prd_posu[2][16];
+static unsigned char quhdu[2],quendu[2];
+static unsigned char devtypeu[2][16] = {{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
+				 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+static struct Scsi_Host * atp_host[2]={NULL,NULL};
+
+static void atp870u_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
+{
+    unsigned short int	tmpcip,id;
+    unsigned char	i,j,h,tarid,lun;
+    unsigned char  *prd;
+    Scsi_Cmnd *workrequ;
+    unsigned int workportu,tmport;
+    unsigned long adrcntu,k;
+    int      errstus;
+
+    for ( h=0; h < 2; h++ )
+    {
+	if ( ( irq & 0x0f ) == irqnumu[h] )
+	{
+	   goto irq_numok;
+	}
+    }
+    return;
+irq_numok:
+    in_int[h]=1;
+    workportu=ioportu[h];
+    tmport=workportu;
+
+    if ( workingu[h] != 0 )
+    {
+       tmport += 0x1f;
+       j=inb(tmport);
+       tmpcip=pciportu[h];
+       if ((inb(tmpcip) & 0x08) != 0)
+       {
+	  tmpcip += 0x2;
+	  while((inb(tmpcip) & 0x08) != 0);
+       }
+       tmpcip=pciportu[h];
+       outb(0x00,tmpcip);
+       tmport -=0x08;
+       i=inb(tmport);
+       if ((j & 0x40) == 0)
+       {
+	  if ((last_cmd[h] & 0x40) == 0)
+	  {
+	     last_cmd[h]=0xff;
+	  }
+       }
+       else
+       {
+	  last_cmd[h] |= 0x40;
+       }
+       tmport -= 0x02;
+       tarid=inb(tmport);
+       tmport += 0x02;
+       if ((tarid & 0x40) != 0)
+       {
+	  tarid=(tarid & 0x07) | 0x08;
+       }
+       else
+       {
+	  tarid &= 0x07;
+       }
+       if ( i == 0x85 )
+       {
+	  if (wide_idu[h] != 0)
+	  {
+	     tmport=workportu+0x1b;
+	     j=inb(tmport) & 0x0e;
+	     j |= 0x01;
+	     outb(j,tmport);
+	  }
+	  if (((quhdu[h] != quendu[h]) || (last_cmd[h] != 0xff)) &&
+	      (in_snd[h] == 0))
+	  {
+	     send_s870(h);
+	  }
+	  in_int[h]=0;
+	  return;
+       }
+       if ( i == 0x21 )
+       {
+	  tmport -= 0x05;
+	  adrcntu=0;
+	  ((unsigned char *)&adrcntu)[2]=inb(tmport++);
+	  ((unsigned char *)&adrcntu)[1]=inb(tmport++);
+	  ((unsigned char *)&adrcntu)[0]=inb(tmport);
+	  k=last_lenu[h][tarid];
+	  k -= adrcntu;
+	  tran_lenu[h][tarid]= k;
+	  last_lenu[h][tarid]=adrcntu;
+	  tmport -= 0x04;
+	  outb(0x41,tmport);
+	  tmport += 0x08;
+	  outb(0x08,tmport);
+	  in_int[h]=0;
+	  return ;
+       }
+
+       if ((i == 0x80) || (i == 0x8f))
+       {
+	  lun=0;
+	  tmport -= 0x07;
+	  j=inb(tmport);
+	  if ( j == 0x44 )
+	  {
+	     tmport += 0x0d;
+	     lun=inb(tmport) & 0x07;
+	  }
+	  else
+	  {
+	     if ( j == 0x41 )
+	     {
+		tmport += 0x02;
+		adrcntu=0;
+		((unsigned char *)&adrcntu)[2]=inb(tmport++);
+		((unsigned char *)&adrcntu)[1]=inb(tmport++);
+		((unsigned char *)&adrcntu)[0]=inb(tmport);
+		k=last_lenu[h][tarid];
+		k -= adrcntu;
+		tran_lenu[h][tarid]= k;
+		last_lenu[h][tarid]=adrcntu;
+		tmport += 0x04;
+		outb(0x08,tmport);
+		in_int[h]=0;
+		return ;
+	     }
+	     else
+	     {
+		outb(0x46,tmport);
+		dirctu[h][tarid]=0x00;
+		tmport += 0x02;
+		outb(0x00,tmport++);
+		outb(0x00,tmport++);
+		outb(0x00,tmport++);
+		tmport+=0x03;
+		outb(0x08,tmport);
+		in_int[h]=0;
+		return;
+	     }
+	  }
+	  tmport=workportu + 0x10;
+	  outb(0x45,tmport);
+	  tmport += 0x06;
+	  tarid=inb(tmport);
+	  if ((tarid & 0x10) != 0)
+	  {
+	     tarid=(tarid & 0x07) | 0x08;
+	  }
+	  else
+	  {
+	     tarid &= 0x07;
+	  }
+	  workrequ=curr_req[h][tarid];
+	  tmport=workportu + 0x0f;
+	  outb(lun,tmport);
+	  tmport += 0x02;
+	  outb(devspu[h][tarid],tmport++);
+	  adrcntu=tran_lenu[h][tarid];
+	  k=last_lenu[h][tarid];
+	  outb(((unsigned char *)&k)[2],tmport++);
+	  outb(((unsigned char *)&k)[1],tmport++);
+	  outb(((unsigned char *)&k)[0],tmport++);
+	  j=tarid;
+	  if ( tarid > 7 )
+	  {
+	     j = (j & 0x07) | 0x40;
+	  }
+	  j |= dirctu[h][tarid];
+	  outb(j,tmport++);
+	  outb(0x80,tmport);
+	  tmport=workportu + 0x1b;
+	  j=inb(tmport) & 0x0e;
+	  id=1;
+	  id=id << tarid;
+	  if ((id & wide_idu[h]) != 0)
+	  {
+	     j |= 0x01;
+	  }
+	  outb(j,tmport);
+	  if ( last_lenu[h][tarid] == 0 )
+	  {
+	     tmport=workportu + 0x18;
+	     outb(0x08,tmport);
+	     in_int[h]=0;
+	     return ;
+	  }
+	  prd=prd_posu[h][tarid];
+	  while ( adrcntu != 0 )
+	  {
+	       id=((unsigned short int *)(prd))[2];
+	       if ( id == 0 )
+	       {
+		  k=0x10000;
+	       }
+	       else
+	       {
+		  k=id;
+	       }
+	       if ( k > adrcntu )
+	       {
+		  ((unsigned short int *)(prd))[2] =(unsigned short int)
+						     (k - adrcntu);
+		  ((unsigned long *)(prd))[0] += adrcntu;
+		  adrcntu=0;
+		  prd_posu[h][tarid]=prd;
+	       }
+	       else
+	       {
+		  adrcntu -= k;
+		  prdaddru[h][tarid] += 0x08;
+		  prd += 0x08;
+		  if ( adrcntu == 0 )
+		  {
+		     prd_posu[h][tarid]=prd;
+		  }
+	       }
+	  }
+	  tmpcip=pciportu[h] + 0x04;
+	  outl(prdaddru[h][tarid],tmpcip);
+	  tmpcip -= 0x02;
+	  outb(0x06,tmpcip);
+	  outb(0x00,tmpcip);
+	  tmpcip -= 0x02;
+	  tmport=workportu + 0x18;
+	  if ( dirctu[h][tarid] != 0 )
+	  {
+	     outb(0x08,tmport);
+	     outb(0x01,tmpcip);
+	     in_int[h]=0;
+	     return;
+	  }
+	  outb(0x08,tmport);
+	  outb(0x09,tmpcip);
+	  in_int[h]=0;
+	  return;
+       }
+
+       workrequ=curr_req[h][tarid];
+       if ( i == 0x42 )
+       {
+	  errstus=0x02;
+	  workrequ->result=errstus;
+	  goto go_42;
+       }
+       if ( i == 0x16 )
+       {
+	  errstus=0;
+	  tmport -= 0x08;
+	  errstus=inb(tmport);
+	  workrequ->result=errstus;
+/*	  if ( errstus == 0x02 )
+	  {
+	     tmport +=0x10;
+	     if ((inb(tmport) & 0x80) != 0)
+	     {
+		printk(" autosense ");
+	     }
+	     tmport -=0x09;
+	     outb(0,tmport);
+	     tmport=workportu+0x3a;
+	     outb((unsigned char)(inb(tmport) | 0x10),tmport);
+	     tmport -= 0x39;
+
+	     outb(0x08,tmport++);
+	     outb(0x7f,tmport++);
+	     outb(0x03,tmport++);
+	     outb(0x00,tmport++);
+	     outb(0x00,tmport++);
+	     outb(0x00,tmport++);
+	     outb(0x0e,tmport++);
+	     outb(0x00,tmport);
+	     tmport+=0x07;
+	     outb(0x00,tmport++);
+	     tmport++;
+	     outb(devspu[h][workrequ->target],tmport++);
+	     outb(0x00,tmport++);
+	     outb(0x00,tmport++);
+	     outb(0x0e,tmport++);
+	     tmport+=0x03;
+	     outb(0x09,tmport);
+	     tmport+=0x07;
+	     i=0;
+	     adrcntu=(unsigned long)(&workrequ->sense_buffer[0]);
+get_sens:
+	     j=inb(tmport);
+	     if ((j & 0x01) != 0)
+	     {
+		tmport-=0x06;
+		(unsigned char)(((caddr_t) adrcntu)[i++])=inb(tmport);
+		tmport+=0x06;
+		goto get_sens;
+	     }
+	     if ((j & 0x80) == 0)
+	     {
+		goto get_sens;
+	     }
+	     if ((j & 0x40) == 0)
+	     {
+		tmport-=0x08;
+		i=inb(tmport);
+	     }
+	     tmport=workportu+0x3a;
+	     outb((unsigned char)(inb(tmport) & 0xef),tmport);
+	     tmport=workportu+0x01;
+	     outb(0x2c,tmport);
+	     tmport += 0x15;
+	     outb(0x80,tmport);
+	  }   */
+go_42:
+	  (*workrequ->scsi_done)(workrequ);
+	  curr_req[h][tarid]=0;
+	  workingu[h]--;
+	  if (wide_idu[h] != 0)
+	  {
+	     tmport=workportu+0x1b;
+	     j=inb(tmport) & 0x0e;
+	     j |= 0x01;
+	     outb(j,tmport);
+	  }
+	  if (((last_cmd[h] != 0xff) || (quhdu[h] != quendu[h])) &&
+	      (in_snd[h] == 0))
+	  {
+	     send_s870(h);
+	  }
+	  in_int[h]=0;
+	  return;
+       }
+   if ( i == 0x4f )
+   {
+      i=0x89;
+   }
+   i &= 0x0f;
+   if ( i == 0x09 )
+   {
+      tmpcip=tmpcip+4;
+      outl(prdaddru[h][tarid],tmpcip);
+      tmpcip=tmpcip-2;
+      outb(0x06,tmpcip);
+      outb(0x00,tmpcip);
+      tmpcip=tmpcip-2;
+      tmport=workportu+0x10;
+      outb(0x41,tmport);
+      dirctu[h][tarid]=0x00;
+      tmport += 0x08;
+      outb(0x08,tmport);
+      outb(0x09,tmpcip);
+      in_int[h]=0;
+      return;
+   }
+   if ( i == 0x08 )
+   {
+      tmpcip=tmpcip+4;
+      outl(prdaddru[h][tarid],tmpcip);
+      tmpcip=tmpcip-2;
+      outb(0x06,tmpcip);
+      outb(0x00,tmpcip);
+      tmpcip=tmpcip-2;
+      tmport=workportu+0x10;
+      outb(0x41,tmport);
+      tmport += 0x05;
+      outb((unsigned char)(inb(tmport) | 0x20),tmport);
+      dirctu[h][tarid]=0x20;
+      tmport += 0x03;
+      outb(0x08,tmport);
+      outb(0x01,tmpcip);
+      in_int[h]=0;
+      return;
+   }
+   tmport -= 0x07;
+   if ( i == 0x0a )
+   {
+      outb(0x30,tmport);
+   }
+   else
+   {
+      outb(0x46,tmport);
+   }
+   dirctu[h][tarid]=0x00;
+   tmport += 0x02;
+   outb(0x00,tmport++);
+   outb(0x00,tmport++);
+   outb(0x00,tmport++);
+   tmport+=0x03;
+   outb(0x08,tmport);
+   in_int[h]=0;
+   return;
+  }
+  else
+  {
+     tmport=workportu+0x17;
+     inb(tmport);
+     workingu[h]=0;
+     in_int[h]=0;
+     return;
+  }
+}
+
+int atp870u_queuecommand(Scsi_Cmnd * req_p, void (*done)(Scsi_Cmnd *))
+{
+    unsigned char i,h;
+    unsigned long flags;
+    unsigned short int m;
+    unsigned int tmport;
+
+    for( h=0; h <= admaxu; h++ )
+    {
+       if ( req_p->host == atp_host[h] )
+       {
+	  goto host_ok;
+       }
+    }
+    return 0;
+host_ok:
+   if ( req_p->channel != 0 )
+   {
+      req_p->result = 0x00040000;
+      done(req_p);
+      return 0;
+   }
+   m=1;
+   m=  m << req_p->target;
+   if ( ( m & active_idu[h] ) == 0 )
+   {
+      req_p->result = 0x00040000;
+      done(req_p);
+      return 0;
+   }
+   if (done)
+   {
+      req_p->scsi_done = done;
+   }
+   else
+   {
+      printk("atp870u_queuecommand: done can't be NULL\n");
+      req_p->result = 0;
+      done(req_p);
+      return 0;
+   }
+   quendu[h]++;
+   if ( quendu[h] >= qcnt )
+   {
+      quendu[h]=0;
+   }
+   wait_que_empty:
+     if ( quhdu[h] == quendu[h] )
+     {
+	goto wait_que_empty;
+     }
+     save_flags(flags);
+     cli();
+     querequ[h][quendu[h]]=req_p;
+     if ( quendu[h] == 0 )
+     {
+	i=qcnt-1;
+     }
+     else
+     {
+	i=quendu[h]-1;
+     }
+     tmport = ioportu[h]+0x1c;
+     restore_flags(flags);
+     if ((inb(tmport) == 0) && (in_int[h] == 0) && (in_snd[h] == 0))
+     {
+	 send_s870(h);
+     }
+     return 0;
+}
+
+void mydlyu(unsigned int dlycnt )
+{
+    unsigned int i ;
+    for ( i = 0 ; i < dlycnt ; i++ )
+    {
+       inb(0x80);
+    }
+}
+
+void send_s870(unsigned char h)
+{
+     unsigned int  tmport;
+     Scsi_Cmnd *workrequ;
+     unsigned long flags;
+     unsigned int   i;
+     unsigned char  j,tarid;
+     unsigned char  *prd;
+     unsigned short int   tmpcip,w;
+     unsigned long  l,bttl;
+     unsigned int workportu;
+     struct scatterlist * sgpnt;
+
+	save_flags(flags);
+	cli();
+	if ( in_snd[h] != 0 )
+	{
+	   restore_flags(flags);
+	   return;
+	}
+	in_snd[h]=1;
+	if ((last_cmd[h] != 0xff) && ((last_cmd[h] & 0x40) != 0))
+	{
+	   last_cmd[h] &= 0x0f;
+	   workrequ=curr_req[h][last_cmd[h]];
+	   goto cmd_subp;
+	}
+	workingu[h]++;
+	j=quhdu[h];
+	quhdu[h]++;
+	if ( quhdu[h] >= qcnt )
+	{
+	   quhdu[h]=0;
+	}
+	workrequ=querequ[h][quhdu[h]];
+	if ( curr_req[h][workrequ->target] == 0 )
+	{
+	   curr_req[h][workrequ->target]=workrequ;
+	   last_cmd[h]=workrequ->target;
+	   goto cmd_subp;
+	}
+	quhdu[h]=j;
+	workingu[h]--;
+	in_snd[h]=0;
+	restore_flags(flags);
+	return ;
+cmd_subp:
+   workportu=ioportu[h];
+   tmport=workportu+0x1f;
+   if ((inb(tmport) & 0xb0) != 0)
+   {
+      goto abortsnd;
+   }
+   tmport=workportu+0x1c;
+   if ( inb(tmport) == 0 )
+   {
+      goto oktosend;
+   }
+abortsnd:
+   last_cmd[h] |= 0x40;
+   in_snd[h]=0;
+   restore_flags(flags);
+   return;
+oktosend:
+   memcpy(&ata_cdbu[h][0], &workrequ->cmnd[0], workrequ->cmd_len);
+   if ( ata_cdbu[h][0] == 0x25 )
+   {
+      if ( workrequ->request_bufflen > 8 )
+      {
+	 workrequ->request_bufflen=0x08;
+      }
+   }
+   if ( ata_cdbu[h][0] == 0x12 )
+   {
+      if ( workrequ->request_bufflen > 0x24 )
+      {
+	 workrequ->request_bufflen = 0x24;
+	 ata_cdbu[h][4]=0x24;
+      }
+   }
+
+   tmport=workportu+0x1b;
+   j=inb(tmport) & 0x0e;
+   tarid=workrequ->target;
+   w=1;
+   w = w << tarid;
+   if ((w & wide_idu[h]) != 0)
+   {
+      j |= 0x01;
+   }
+   outb(j,tmport);
+   tmport=workportu;
+   outb(workrequ->cmd_len,tmport++);
+   outb(0x2c,tmport++);
+   outb(0xcf,tmport++);
+   for ( i=0 ; i < workrequ->cmd_len ; i++ )
+   {
+       outb(ata_cdbu[h][i],tmport++);
+   }
+   tmport=workportu+0x0f;
+   outb(0x00,tmport);
+   tmport+=0x02;
+   outb(devspu[h][tarid],tmport++);
+   if (workrequ->use_sg)
+   {
+
+     l=0;
+     sgpnt = (struct scatterlist *) workrequ->request_buffer;
+     for(i=0; i<workrequ->use_sg; i++)
+     {
+       if(sgpnt[i].length == 0 || workrequ->use_sg > ATP870U_SCATTER)
+       {
+	 panic("Foooooooood fight!");
+       }
+       l += sgpnt[i].length;
+     }
+   }
+   else
+   {
+     l=workrequ->request_bufflen;
+   }
+   outb((unsigned char)(((unsigned char *)(&l))[2]),tmport++);
+   outb((unsigned char)(((unsigned char *)(&l))[1]),tmport++);
+   outb((unsigned char)(((unsigned char *)(&l))[0]),tmport++);
+   j=tarid;
+   last_lenu[h][j]=l;
+   tran_lenu[h][j]=0;
+   if ((j & 0x08) != 0)
+   {
+      j=(j & 0x07) | 0x40;
+   }
+   if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) ||
+       (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15))
+   {
+      outb((unsigned char)(j | 0x20),tmport++);
+   }
+   else
+   {
+      outb(j,tmport++);
+   }
+   outb(0x80,tmport);
+   tmport=workportu + 0x1c;
+   dirctu[h][tarid]=0;
+   if ( l == 0 )
+   {
+      if ( inb(tmport) == 0 )
+      {
+	 tmport=workportu+0x18;
+	 outb(0x08,tmport);
+      }
+      else
+      {
+	last_cmd[h] |= 0x40;
+      }
+      in_snd[h]=0;
+      restore_flags(flags);
+      return;
+   }
+   tmpcip=pciportu[h];
+   prd=&prd_tableu[h][tarid][0];
+   prd_posu[h][tarid]=prd;
+   if (workrequ->use_sg)
+   {
+     sgpnt = (struct scatterlist *) workrequ->request_buffer;
+     i=0;
+     for(j=0; j<workrequ->use_sg; j++)
+     {
+	(unsigned long)(((unsigned long *)(prd))[i >> 1])=(unsigned long)sgpnt[j].address;
+	(unsigned short int)(((unsigned short int *)(prd))[i+2])=sgpnt[j].length;
+	(unsigned short int)(((unsigned short int *)(prd))[i+3])=0;
+	i +=0x04;
+     }
+     (unsigned short int)(((unsigned short int *)(prd))[i-1])=0x8000;
+   }
+   else
+   {
+     bttl=(unsigned long)workrequ->request_buffer;
+     l=workrequ->request_bufflen;
+     i=0;
+     while ( l > 0x10000 )
+     {
+	(unsigned short int)(((unsigned short int *)(prd))[i+3])=0x0000;
+	(unsigned short int)(((unsigned short int *)(prd))[i+2])=0x0000;
+	(unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl;
+	l -= 0x10000;
+	bttl += 0x10000;
+	i += 0x04;
+     }
+     (unsigned short int)(((unsigned short int *)(prd))[i+3])=0x8000;
+     (unsigned short int)(((unsigned short int *)(prd))[i+2])=l;
+     (unsigned long)(((unsigned long *)(prd))[i >> 1])=bttl;
+   }
+   tmpcip=tmpcip+4;
+   prdaddru[h][tarid]=(unsigned long)&prd_tableu[h][tarid][0];
+   outl(prdaddru[h][tarid],tmpcip);
+   tmpcip=tmpcip-2;
+   outb(0x06,tmpcip);
+   outb(0x00,tmpcip);
+   tmpcip=tmpcip-2;
+   if ((ata_cdbu[h][0] == 0x0a) || (ata_cdbu[h][0] == 0x2a) ||
+       (ata_cdbu[h][0] == 0xaa) || (ata_cdbu[h][0] == 0x15))
+   {
+      dirctu[h][tarid]=0x20;
+      if ( inb(tmport) == 0 )
+      {
+	 tmport=workportu+0x18;
+	 outb(0x08,tmport);
+	 outb(0x01,tmpcip);
+      }
+      else
+      {
+	 last_cmd[h] |= 0x40;
+      }
+      in_snd[h]=0;
+      restore_flags(flags);
+      return;
+   }
+   if ( inb(tmport) == 0 )
+   {
+      tmport=workportu+0x18;
+      outb(0x08,tmport);
+      outb(0x09,tmpcip);
+   }
+   else
+   {
+      last_cmd[h] |= 0x40;
+   }
+   in_snd[h]=0;
+   restore_flags(flags);
+   return;
+
+}
+
+static void internal_done(Scsi_Cmnd * SCpnt)
+{
+	SCpnt->SCp.Status++;
+}
+
+int atp870u_command(Scsi_Cmnd * SCpnt)
+{
+
+    atp870u_queuecommand(SCpnt, internal_done);
+
+    SCpnt->SCp.Status = 0;
+    while (!SCpnt->SCp.Status)
+	barrier();
+    return SCpnt->result;
+}
+
+unsigned char fun_scam ( unsigned char host,unsigned short int * val )
+{
+    unsigned int  tmport ;
+    unsigned short int	 i,k;
+    unsigned char     j;
+
+    tmport = ioportu[host]+0x1c;
+    outw(*val,tmport);
+FUN_D7:
+    for ( i=0; i < 10; i++ )	     /* stable >= bus settle delay(400 ns)  */
+    {
+	k=inw(tmport);
+	j= (unsigned char)(k >> 8);
+	if ((k & 0x8000) != 0)	     /* DB7 all release?    */
+	{
+	   goto  FUN_D7;
+	}
+    }
+    *val |= 0x4000;		    /* assert DB6	    */
+    outw(*val,tmport);
+    *val &= 0xdfff;		    /* assert DB5	    */
+    outw(*val,tmport);
+FUN_D5:
+    for ( i=0; i < 10; i++ )	    /* stable >= bus settle delay(400 ns) */
+    {
+       if ((inw(tmport) & 0x2000) != 0)   /* DB5 all release?	*/
+       {
+	  goto	FUN_D5;
+       }
+    }
+    *val |= 0x8000;		     /* no DB4-0, assert DB7	*/
+    *val &= 0xe0ff;
+    outw(*val,tmport);
+    *val &= 0xbfff;		     /* release DB6		*/
+    outw(*val,tmport);
+FUN_D6:
+    for ( i=0; i < 10; i++ )	     /* stable >= bus settle delay(400 ns)  */
+    {
+       if ((inw(tmport) & 0x4000) != 0)   /* DB6 all release?  */
+       {
+	  goto	FUN_D6;
+       }
+    }
+
+    return j;
+}
+
+void tscam( unsigned char host )
+{
+
+    unsigned int  tmport ;
+    unsigned char  i,j,k;
+    unsigned long  n;
+    unsigned short int	m,assignid_map,val;
+    unsigned char  mbuf[33],quintet[2];
+    static unsigned char g2q_tab[8]={ 0x38,0x31,0x32,0x2b,0x34,0x2d,0x2e,0x27 };
+
+
+    for ( i=0; i < 0x10; i++ )
+    {
+	mydlyu(0xffff);
+    }
+
+    tmport = ioportu[host]+1;
+    outb(0x08,tmport++);
+    outb(0x7f,tmport);
+    tmport = ioportu[host]+0x11;
+    outb(0x20,tmport);
+
+    if ((scam_on[host] & 0x40) == 0)
+    {
+       return;
+    }
+
+    m=1;
+    m <<= host_idu[host];
+    j=16;
+    if ( chip_veru[host] < 4 )
+    {
+       m |= 0xff00;
+       j=8;
+    }
+    assignid_map=m;
+    tmport = ioportu[host]+0x02;
+    outb(0x02,tmport++);	/* 2*2=4ms,3EH 2/32*3E=3.9ms */
+    outb(0,tmport++);
+    outb(0,tmport++);
+    outb(0,tmport++);
+    outb(0,tmport++);
+    outb(0,tmport++);
+    outb(0,tmport++);
+
+    for ( i = 0 ; i < j ; i ++ )
+    {
+	m=1;
+	m=m<<i;
+	if ( ( m & assignid_map ) != 0 )
+	{
+	   continue;
+	}
+    tmport = ioportu[host]+0x0f;
+    outb(0,tmport++);
+    tmport += 0x02;
+    outb(0,tmport++);
+    outb(0,tmport++);
+    outb(0,tmport++);
+    if ( i > 7 )
+    {
+       k=(i & 0x07) | 0x40;
+    }
+    else
+    {
+       k=i;
+    }
+    outb(k,tmport++);
+    tmport = ioportu[host]+0x1b;
+    if ( chip_veru[host] == 4 )
+    {
+       outb((unsigned char)((inb(tmport) & 0x0e) | 0x01),tmport);
+    }
+    else
+    {
+       outb((unsigned char)(inb(tmport) & 0x0e),tmport);
+    }
+wait_rdyok:
+    tmport = ioportu[host]+0x18;
+    outb(0x09,tmport);
+    tmport += 0x07;
+
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport -= 0x08;
+    k=inb(tmport);
+    if ( k != 0x16 )
+    {
+       if ((k == 0x85) || (k == 0x42))
+       {
+	  continue;
+       }
+       tmport = ioportu[host]+0x10;
+       outb(0x41,tmport);
+       goto wait_rdyok;
+    }
+    assignid_map |= m;
+
+    }
+    tmport = ioportu[host]+0x02;
+    outb(0x7f,tmport);
+    tmport = ioportu[host]+0x1b;
+    outb(0x02,tmport);
+
+    outb(0,0x80);
+
+    val=0x0080;      /* bsy  */
+    tmport = ioportu[host]+0x1c;
+    outw(val,tmport);
+    val |=0x0040;    /* sel  */
+    outw(val,tmport);
+    val |=0x0004;    /* msg  */
+    outw(val,tmport);
+    inb(0x80);		      /* 2 deskew delay(45ns*2=90ns) */
+    val &=0x007f;    /* no bsy	*/
+    outw(val,tmport);
+    mydlyu(0xffff);  /* recommanded SCAM selection response time */
+    mydlyu(0xffff);
+    val &=0x00fb;    /* after 1ms no msg */
+    outw(val,tmport);
+wait_nomsg:
+    if ((inb(tmport) & 0x04) != 0)
+    {
+       goto wait_nomsg;
+    }
+    outb(1,0x80);
+    mydlyu(100);
+    for ( n=0; n < 0x30000; n++ )
+    {
+	if ((inb(tmport) & 0x80) != 0)	   /* bsy ? */
+	{
+	   goto wait_io;
+	}
+    }
+    goto  TCM_SYNC;
+wait_io:
+    for ( n=0; n < 0x30000; n++ )
+    {
+	if ((inb(tmport) & 0x81) == 0x0081)
+	{
+	   goto wait_io1;
+	}
+    }
+    goto  TCM_SYNC;
+wait_io1:
+    inb(0x80);
+    val |=0x8003;    /* io,cd,db7  */
+    outw(val,tmport);
+    inb(0x80);
+    val &=0x00bf;    /* no sel	   */
+    outw(val,tmport);
+    outb(2,0x80);
+TCM_SYNC:
+    mydlyu(0x800);
+    if ((inb(tmport) & 0x80) == 0x00)	 /* bsy ? */
+    {
+       outw(0,tmport--);
+       outb(0,tmport);
+       tmport=ioportu[host] + 0x15;
+       outb(0,tmport);
+       tmport += 0x03;
+       outb(0x09,tmport);
+       tmport += 0x07;
+       while ((inb(tmport) & 0x80) == 0);
+       tmport -= 0x08;
+       inb(tmport);
+       return;
+    }
+
+    val &= 0x00ff;		 /* synchronization  */
+    val |= 0x3f00;
+    fun_scam(host,&val);
+    outb(3,0x80);
+    val &= 0x00ff;		 /* isolation	     */
+    val |= 0x2000;
+    fun_scam(host,&val);
+    outb(4,0x80);
+    i=8;
+    j=0;
+TCM_ID:
+    if ((inw(tmport) & 0x2000) == 0)
+    {
+       goto TCM_ID;
+    }
+    outb(5,0x80);
+    val &= 0x00ff;		 /* get ID_STRING */
+    val |= 0x2000;
+    k=fun_scam(host,&val);
+    if ((k & 0x03) == 0)
+    {
+       goto TCM_5;
+    }
+    mbuf[j] <<= 0x01;
+    mbuf[j] &= 0xfe;
+    if ((k & 0x02) != 0)
+    {
+       mbuf[j] |= 0x01;
+    }
+    i--;
+    if ( i > 0 )
+    {
+       goto TCM_ID;
+    }
+    j++;
+    i=8;
+    goto TCM_ID;
+
+TCM_5:			     /* isolation complete..  */
+/*    mbuf[32]=0;
+    printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
+    i=15;
+    j=mbuf[0];
+    if ((j & 0x20) != 0)     /* bit5=1:ID upto 7      */
+    {
+       i=7;
+    }
+    if ((j & 0x06) == 0)     /* IDvalid?	      */
+    {
+       goto  G2Q5;
+    }
+    k=mbuf[1];
+small_id:
+    m=1;
+    m <<= k;
+    if ((m & assignid_map) == 0)
+    {
+       goto G2Q_QUIN;
+    }
+    if ( k > 0 )
+    {
+       k--;
+       goto small_id;
+    }
+G2Q5:			      /* srch from max acceptable ID#  */
+    k=i;		      /* max acceptable ID#	       */
+G2Q_LP:
+    m=1;
+    m <<= k;
+    if ((m & assignid_map) == 0)
+    {
+       goto G2Q_QUIN;
+    }
+    if ( k > 0 )
+    {
+       k--;
+       goto G2Q_LP;
+    }
+G2Q_QUIN:		      /* k=binID#,	 */
+    assignid_map |= m;
+    if ( k < 8 )
+    {
+       quintet[0]=0x38;       /* 1st dft ID<8	 */
+    }
+    else
+    {
+       quintet[0]=0x31;       /* 1st  ID>=8	 */
+    }
+    k &= 0x07;
+    quintet[1]=g2q_tab[k];
+
+    val &= 0x00ff;	       /* AssignID 1stQuintet,AH=001xxxxx  */
+    m=quintet[0] << 8;
+    val |= m;
+    fun_scam(host,&val);
+    val &= 0x00ff;	       /* AssignID 2ndQuintet,AH=001xxxxx */
+    m=quintet[1] << 8;
+    val |= m;
+    fun_scam(host,&val);
+
+    goto TCM_SYNC;
+
+}
+
+void is870(unsigned long host,unsigned int wkport )
+{
+    unsigned int  tmport ;
+    unsigned char i,j,k,rmb;
+    unsigned short int m;
+    static unsigned char mbuf[512];
+    static unsigned char satn[9] = { 0,0,0,0,0,0,0,6,6 };
+    static unsigned char inqd[9] = { 0x12,0,0,0,0x24,0,0,0x24,6 };
+    static unsigned char synn[6] = { 0x80,1,3,1,0x19,0x0e };
+    static unsigned char synu[6] = { 0x80,1,3,1,0x0c,0x0e };
+    static unsigned char synw[6] = { 0x80,1,3,1,0x0c,0x07 };
+    static unsigned char wide[6] = { 0x80,1,2,3,1,0 };
+
+    sync_idu=0;
+    tmport=wkport+0x3a;
+    outb((unsigned char)(inb(tmport) | 0x10),tmport);
+
+    for ( i = 0 ; i < 16 ; i ++ )
+    {
+	if ((chip_veru[host] != 4) && (i > 7))
+	{
+	   break;
+	}
+	m=1;
+	m=m<<i;
+	if ( ( m & active_idu[host] ) != 0 )
+	{
+	   continue;
+	}
+	if ( i == host_idu[host] )
+	{
+	   printk("         ID: %2d  Host Adapter\n",host_idu[host]);
+	   continue;
+	}
+	if ( chip_veru[host] == 4 )
+	{
+	   tmport=wkport+0x1b;
+	   j=(inb(tmport) & 0x0e) | 0x01;
+	   outb(j,tmport);
+	}
+    tmport=wkport+1;
+    outb(0x08,tmport++);
+    outb(0x7f,tmport++);
+    outb(satn[0],tmport++);
+    outb(satn[1],tmport++);
+    outb(satn[2],tmport++);
+    outb(satn[3],tmport++);
+    outb(satn[4],tmport++);
+    outb(satn[5],tmport++);
+    tmport+=0x06;
+    outb(0,tmport);
+    tmport+=0x02;
+    outb(devspu[host][i],tmport++);
+    outb(0,tmport++);
+    outb(satn[6],tmport++);
+    outb(satn[7],tmport++);
+    j=i;
+    if ((j & 0x08) != 0)
+    {
+       j=(j & 0x07) | 0x40;
+    }
+    outb(j,tmport);
+    tmport+=0x03;
+    outb(satn[8],tmport);
+    tmport+=0x07;
+
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+    {
+       continue;
+    }
+    while ( inb(tmport) != 0x8e );
+    active_idu[host] |= m;
+
+    tmport=wkport+0x10;
+    outb(0x30,tmport);
+    tmport=wkport+0x04;
+    outb(0x00,tmport);
+
+phase_cmd:
+    tmport=wkport+0x18;
+    outb(0x08,tmport);
+    tmport+=0x07;
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    j=inb(tmport);
+    if ( j != 0x16 )
+    {
+       tmport=wkport+0x10;
+       outb(0x41,tmport);
+       goto phase_cmd;
+    }
+sel_ok:
+       tmport=wkport+3;
+       outb(inqd[0],tmport++);
+       outb(inqd[1],tmport++);
+       outb(inqd[2],tmport++);
+       outb(inqd[3],tmport++);
+       outb(inqd[4],tmport++);
+       outb(inqd[5],tmport);
+       tmport+=0x07;
+       outb(0,tmport);
+       tmport+=0x02;
+       outb(devspu[host][i],tmport++);
+       outb(0,tmport++);
+       outb(inqd[6],tmport++);
+       outb(inqd[7],tmport++);
+       tmport+=0x03;
+       outb(inqd[8],tmport);
+       tmport+=0x07;
+       while ((inb(tmport) & 0x80) == 0x00);
+       tmport-=0x08;
+       if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+       {
+	  continue;
+       }
+       while ( inb(tmport) != 0x8e );
+       if ( chip_veru[host] == 4 )
+       {
+	  tmport=wkport+0x1b;
+	  j=inb(tmport) & 0x0e;
+	  outb(j,tmport);
+       }
+       tmport=wkport+0x18;
+       outb(0x08,tmport);
+       tmport += 0x07;
+       j=0;
+rd_inq_data:
+       k=inb(tmport);
+       if ((k & 0x01) != 0 )
+       {
+	  tmport-=0x06;
+	  mbuf[j++]=inb(tmport);
+	  tmport+=0x06;
+	  goto rd_inq_data;
+       }
+       if ((k & 0x80) == 0 )
+       {
+	  goto rd_inq_data;
+       }
+       tmport-=0x08;
+       j=inb(tmport);
+       if ( j == 0x16 )
+       {
+	  goto inq_ok;
+       }
+    tmport=wkport+0x10;
+    outb(0x46,tmport);
+    tmport+=0x02;
+    outb(0,tmport++);
+    outb(0,tmport++);
+    outb(0,tmport++);
+    tmport+=0x03;
+    outb(0x08,tmport);
+    tmport+=0x07;
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    if (inb(tmport) != 0x16)
+    {
+       goto sel_ok;
+    }
+inq_ok:
+     mbuf[36]=0;
+     printk("         ID: %2d  %s\n",i,&mbuf[8]);
+     devtypeu[host][i]=mbuf[0];
+     rmb=mbuf[1];
+     if ( chip_veru[host] != 4 )
+     {
+	goto not_wide;
+     }
+     if ((mbuf[7] & 0x60) == 0)
+     {
+	goto not_wide;
+     }
+     if ((global_map[host] & 0x20) == 0)
+     {
+	goto not_wide;
+     }
+     tmport=wkport+0x1b;
+     j=(inb(tmport) & 0x0e) | 0x01;
+     outb(j,tmport);
+    tmport=wkport+3;
+    outb(satn[0],tmport++);
+    outb(satn[1],tmport++);
+    outb(satn[2],tmport++);
+    outb(satn[3],tmport++);
+    outb(satn[4],tmport++);
+    outb(satn[5],tmport++);
+    tmport+=0x06;
+    outb(0,tmport);
+    tmport+=0x02;
+    outb(devspu[host][i],tmport++);
+    outb(0,tmport++);
+    outb(satn[6],tmport++);
+    outb(satn[7],tmport++);
+    tmport+=0x03;
+    outb(satn[8],tmport);
+    tmport+=0x07;
+
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+    {
+       continue;
+    }
+    while ( inb(tmport) != 0x8e );
+try_wide:
+    j=0;
+    tmport=wkport+0x14;
+    outb(0x05,tmport);
+    tmport += 0x04;
+    outb(0x20,tmport);
+    tmport+=0x07;
+
+    while ((inb(tmport) & 0x80) == 0 )
+    {
+       if ((inb(tmport) & 0x01) != 0 )
+       {
+	  tmport-=0x06;
+	  outb(wide[j++],tmport);
+	  tmport+=0x06;
+       }
+    }
+    tmport-=0x08;
+    while ((inb(tmport) & 0x80) == 0x00);
+    j=inb(tmport) & 0x0f;
+    if ( j == 0x0f )
+    {
+       goto widep_in;
+    }
+    if ( j == 0x0a )
+    {
+       goto widep_cmd;
+    }
+    if ( j == 0x0e )
+    {
+       goto try_wide;
+    }
+    continue;
+widep_out:
+    tmport=wkport+0x18;
+    outb(0x20,tmport);
+    tmport+=0x07;
+    while ((inb(tmport) & 0x80) == 0 )
+    {
+	if ((inb(tmport) & 0x01) != 0 )
+	{
+	   tmport-=0x06;
+	   outb(0,tmport);
+	   tmport+=0x06;
+	}
+    }
+    tmport-=0x08;
+    j=inb(tmport) & 0x0f;
+    if ( j == 0x0f )
+    {
+       goto widep_in;
+    }
+    if ( j == 0x0a )
+    {
+       goto widep_cmd;
+    }
+    if ( j == 0x0e )
+    {
+       goto widep_out;
+    }
+    continue;
+widep_in:
+    tmport=wkport+0x14;
+    outb(0xff,tmport);
+    tmport += 0x04;
+    outb(0x20,tmport);
+    tmport+=0x07;
+    k=0;
+widep_in1:
+    j=inb(tmport);
+    if ((j & 0x01) != 0)
+    {
+       tmport-=0x06;
+       mbuf[k++]=inb(tmport);
+       tmport+=0x06;
+       goto widep_in1;
+    }
+    if ((j & 0x80) == 0x00)
+    {
+       goto widep_in1;
+    }
+    tmport-=0x08;
+    j=inb(tmport) & 0x0f;
+    if ( j == 0x0f )
+    {
+       goto widep_in;
+    }
+    if ( j == 0x0a )
+    {
+       goto widep_cmd;
+    }
+    if ( j == 0x0e )
+    {
+       goto widep_out;
+    }
+    continue;
+widep_cmd:
+    tmport=wkport+0x10;
+    outb(0x30,tmport);
+    tmport=wkport+0x14;
+    outb(0x00,tmport);
+    tmport+=0x04;
+    outb(0x08,tmport);
+    tmport+=0x07;
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    j=inb(tmport);
+    if ( j != 0x16 )
+    {
+       if ( j == 0x4e )
+       {
+	  goto widep_out;
+       }
+       continue;
+    }
+    if ( mbuf[0] != 0x01 )
+    {
+       goto not_wide;
+    }
+    if ( mbuf[1] != 0x02 )
+    {
+       goto not_wide;
+    }
+    if ( mbuf[2] != 0x03 )
+    {
+       goto not_wide;
+    }
+    if ( mbuf[3] != 0x01 )
+    {
+       goto not_wide;
+    }
+    m=1;
+    m = m << i;
+    wide_idu[host] |= m;
+not_wide:
+    if ((devtypeu[host][i] == 0x00) || (devtypeu[host][i] == 0x07))
+    {
+       goto set_sync;
+    }
+    continue;
+set_sync:
+    tmport=wkport+0x1b;
+    j=inb(tmport) & 0x0e;
+    if ((m & wide_idu[host]) != 0 )
+    {
+       j |= 0x01;
+    }
+    outb(j,tmport);
+    tmport=wkport+3;
+    outb(satn[0],tmport++);
+    outb(satn[1],tmport++);
+    outb(satn[2],tmport++);
+    outb(satn[3],tmport++);
+    outb(satn[4],tmport++);
+    outb(satn[5],tmport++);
+    tmport+=0x06;
+    outb(0,tmport);
+    tmport+=0x02;
+    outb(devspu[host][i],tmport++);
+    outb(0,tmport++);
+    outb(satn[6],tmport++);
+    outb(satn[7],tmport++);
+    tmport+=0x03;
+    outb(satn[8],tmport);
+    tmport+=0x07;
+
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e))
+    {
+       continue;
+    }
+    while ( inb(tmport) != 0x8e);
+try_sync:
+    j=0;
+    tmport=wkport+0x14;
+    outb(0x06,tmport);
+    tmport += 0x04;
+    outb(0x20,tmport);
+    tmport+=0x07;
+
+    while ((inb(tmport) & 0x80) == 0 )
+    {
+       if ((inb(tmport) & 0x01) != 0 )
+       {
+	  tmport-=0x06;
+	  if ( rmb != 0 )
+	  {
+	     outb(synn[j++],tmport);
+	  }
+	  else
+	  {
+	     if ((m & wide_idu[host]) != 0)
+	     {
+		outb(synw[j++],tmport);
+	     }
+	     else
+	     {
+		if ((m & ultra_map[host]) != 0)
+		{
+		   outb(synu[j++],tmport);
+		}
+		else
+		{
+		   outb(synn[j++],tmport);
+		}
+	     }
+	  }
+	  tmport+=0x06;
+       }
+    }
+    tmport-=0x08;
+    while ((inb(tmport) & 0x80) == 0x00);
+    j=inb(tmport) & 0x0f;
+    if ( j == 0x0f )
+    {
+       goto phase_ins;
+    }
+    if ( j == 0x0a )
+    {
+       goto phase_cmds;
+    }
+    if ( j == 0x0e )
+    {
+       goto try_sync;
+    }
+    continue;
+phase_outs:
+    tmport=wkport+0x18;
+    outb(0x20,tmport);
+    tmport+=0x07;
+    while ((inb(tmport) & 0x80) == 0x00)
+    {
+      if ((inb(tmport) & 0x01) != 0x00)
+      {
+	 tmport-=0x06;
+	 outb(0x00,tmport);
+	 tmport+=0x06;
+      }
+    }
+    tmport-=0x08;
+    j=inb(tmport);
+    if ( j == 0x85 )
+    {
+       goto tar_dcons;
+    }
+    j &= 0x0f;
+    if ( j == 0x0f )
+    {
+       goto phase_ins;
+    }
+    if ( j == 0x0a )
+    {
+       goto phase_cmds;
+    }
+    if ( j == 0x0e )
+    {
+       goto phase_outs;
+    }
+    continue;
+phase_ins:
+    tmport=wkport+0x14;
+    outb(0xff,tmport);
+    tmport += 0x04;
+    outb(0x20,tmport);
+    tmport+=0x07;
+    k=0;
+phase_ins1:
+    j=inb(tmport);
+    if ((j & 0x01) != 0x00)
+    {
+       tmport-=0x06;
+       mbuf[k++]=inb(tmport);
+       tmport+=0x06;
+       goto phase_ins1;
+    }
+    if ((j & 0x80) == 0x00)
+    {
+       goto phase_ins1;
+    }
+    tmport-=0x08;
+    while ((inb(tmport) & 0x80) == 0x00);
+    j=inb(tmport);
+    if ( j == 0x85 )
+    {
+       goto tar_dcons;
+    }
+    j &= 0x0f;
+    if ( j == 0x0f )
+    {
+       goto phase_ins;
+    }
+    if ( j == 0x0a )
+    {
+       goto phase_cmds;
+    }
+    if ( j == 0x0e )
+    {
+       goto phase_outs;
+    }
+    continue;
+phase_cmds:
+    tmport=wkport+0x10;
+    outb(0x30,tmport);
+tar_dcons:
+    tmport=wkport+0x14;
+    outb(0x00,tmport);
+    tmport+=0x04;
+    outb(0x08,tmport);
+    tmport+=0x07;
+    while ((inb(tmport) & 0x80) == 0x00);
+    tmport-=0x08;
+    j=inb(tmport);
+    if ( j != 0x16 )
+    {
+       continue;
+    }
+    if ( mbuf[0] != 0x01 )
+    {
+       continue;
+    }
+    if ( mbuf[1] != 0x03 )
+    {
+       continue;
+    }
+    if ( mbuf[4] == 0x00 )
+    {
+       continue;
+    }
+    if ( mbuf[3] > 0x64 )
+    {
+       continue;
+    }
+    if ( mbuf[4] > 0x0c )
+    {
+       mbuf[4]=0x0c;
+    }
+    devspu[host][i] = mbuf[4];
+    if ((mbuf[3] < 0x0d) && (rmb == 0))
+    {
+       j=0xa0;
+       goto set_syn_ok;
+    }
+    if ( mbuf[3] < 0x1a )
+    {
+       j=0x20;
+       goto set_syn_ok;
+    }
+    if ( mbuf[3] < 0x33 )
+    {
+       j=0x40;
+       goto set_syn_ok;
+    }
+    if ( mbuf[3] < 0x4c )
+    {
+       j=0x50;
+       goto set_syn_ok;
+    }
+    j=0x60;
+set_syn_ok:
+    devspu[host][i] = (devspu[host][i] & 0x0f) | j;
+   }
+   tmport=wkport+0x3a;
+   outb((unsigned char)(inb(tmport) & 0xef),tmport);
+}
+
+/* return non-zero on detection */
+int atp870u_detect(Scsi_Host_Template * tpnt)
+{
+    unsigned char irq,h,k;
+    unsigned long flags;
+    unsigned int base_io,error,tmport;
+    unsigned short index = 0;
+    unsigned char pci_bus[3], pci_device_fn[3], chip_ver[3],host_id;
+    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;
+
+    printk("aec671x_detect: \n");
+    if (!pci_present())
+    {
+       printk("   NO BIOS32 SUPPORT.\n");
+       return count;
+    }
+
+    tpnt->proc_dir = &proc_scsi_atp870u;
+
+    for ( h = 0 ; h < 2 ; h++ )
+    {
+      active_idu[h]=0;
+      wide_idu[h]=0;
+      host_idu[h]=0x07;
+      quhdu[h]=0;
+      quendu[h]=0;
+      pci_bus[h]=0;
+      pci_device_fn[h]=0xff;
+      chip_ver[h]=0;
+      last_cmd[h]=0xff;
+      in_snd[h]=0;
+      in_int[h]=0;
+      for ( k = 0 ; k < qcnt ; k++ )
+      {
+	  querequ[h][k]=0;
+      }
+      for ( k = 0 ; k < 16 ; k++ )
+      {
+	  curr_req[h][k]=0;
+      }
+    }
+    h=0;
+    while ( devid[h] != 0 )
+    {
+      pci_find_device(0x1191,devid[h],pdev);
+      if (pdev == NULL); {
+	  h++;
+	  index=0;
+	  continue;
+       }
+       chip_ver[2]=0;
+	   
+       /* To avoid messing with the things below...  */
+       pci_device_fn[2] =  pdev->devfn;
+       pci_bus[2] = pdev->bus->number;
+
+       if ( devid[h] == 0x8002 )
+       {
+	  error = pci_read_config_byte(pdev,0x08,&chip_ver[2]);
+	  if ( chip_ver[2] < 2 )
+	  {
+	     goto nxt_devfn;
+	  }
+       }
+       if ( devid[h] == 0x8010 )
+       {
+	  chip_ver[2]=0x04;
+       }
+       if ( pci_device_fn[2] < pci_device_fn[0] )
+       {
+	  pci_bus[1]=pci_bus[0];
+	  pci_device_fn[1]=pci_device_fn[0];
+	  chip_ver[1]=chip_ver[0];
+	  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] )
+       {
+	  pci_bus[1]=pci_bus[2];
+	  pci_device_fn[1]=pci_device_fn[2];
+	  chip_ver[1]=chip_ver[2];
+       }
+nxt_devfn:
+       index++;
+       if ( index > 3 )
+       {
+	  index=0;
+	  h++;
+       }
+    }
+    for ( h=0; h < 2; h++ )
+    {
+    if ( pci_device_fn[h] == 0xff )
+    {
+       return count;
+    }
+
+    pdev->devfn = pci_device_fn[h];
+    pdev->bus->number = pci_bus[h];
+
+    /* Found an atp870u/w. */
+    error = pci_read_config_dword(pdev,0x10,&base_io);
+    error += pci_read_config_byte(pdev,0x3c,&irq);
+    error += pci_read_config_byte(pdev,0x49,&host_id);
+
+    base_io &= 0xfffffff8;
+    printk("   ACARD AEC-671X PCI Ultra/W SCSI-3 Host Adapter: %d    IO:%x, IRQ:%d.\n"
+			     ,h,base_io,irq);
+    ioportu[h]=base_io;
+    pciportu[h]=base_io + 0x20;
+    irqnumu[h]=irq;
+    host_id &= 0x07;
+    host_idu[h]=host_id;
+    chip_veru[h]=chip_ver[h];
+
+    tmport=base_io+0x22;
+    scam_on[h]=inb(tmport);
+    tmport += 0x0b;
+    global_map[h]=inb(tmport++);
+    ultra_map[h]=inw(tmport);
+    if ( ultra_map[h] == 0 )
+    {
+       scam_on[h]=0x00;
+       global_map[h]=0x20;
+       ultra_map[h]=0xffff;
+    }
+
+    shpnt = scsi_register(tpnt,4);
+
+    save_flags(flags);
+    cli();
+    if (request_irq(irq,atp870u_intr_handle, 0, "atp870u", NULL))
+    {
+       printk("Unable to allocate IRQ for Acard controller.\n");
+       goto unregister;
+    }
+
+    tmport=base_io+0x3a;
+    k=(inb(tmport) & 0xf3) | 0x10;
+    outb(k,tmport);
+    outb((k & 0xdf),tmport);
+    mydlyu(0x8000);
+    outb(k,tmport);
+    mydlyu(0x8000);
+    tmport=base_io;
+    outb((host_id | 0x08),tmport);
+    tmport += 0x18;
+    outb(0,tmport);
+    tmport += 0x07;
+    while ((inb(tmport) & 0x80) == 0);
+    tmport -= 0x08;
+    inb(tmport);
+    tmport = base_io +1;
+    outb(8,tmport++);
+    outb(0x7f,tmport);
+    tmport = base_io + 0x11;
+    outb(0x20,tmport);
+
+    tscam(h);
+    is870(h,base_io);
+    tmport=base_io+0x3a;
+    outb((inb(tmport) & 0xef),tmport);
+
+    atp_host[h] = shpnt;
+    if ( chip_ver[h] == 4 )
+    {
+       shpnt->max_id = 16;
+    }
+    shpnt->this_id = host_id;
+    shpnt->unique_id = base_io;
+    shpnt->io_port = base_io;
+    shpnt->n_io_port = 0x40;  /* Number of bytes of I/O space used */
+    shpnt->irq = irq;
+    restore_flags(flags);
+    request_region(base_io, 0x40,"atp870u");  /* Register the IO ports that we use */
+    count++;
+    index++;
+    continue;
+unregister:
+    scsi_unregister(shpnt);
+    restore_flags(flags);
+    index++;
+    continue;
+    }
+
+    return count;
+}
+
+/* The abort command does not leave the device in a clean state where
+   it is available to be used again.  Until this gets worked out, we will
+   leave it commented out.  */
+
+int atp870u_abort(Scsi_Cmnd * SCpnt)
+{
+    unsigned char h,j;
+    unsigned int  tmport;
+/*    printk(" atp870u_abort: \n");   */
+    for ( h=0; h <= admaxu; h++ )
+    {
+	if ( SCpnt->host == atp_host[h] )
+	{
+	   goto find_adp;
+	}
+    }
+    panic("Abort host not found !");
+find_adp:
+    printk(" workingu=%x last_cmd=%x ",workingu[h],last_cmd[h]);
+    printk(" quhdu=%x quendu=%x ",quhdu[h],quendu[h]);
+    tmport=ioportu[h];
+    for ( j=0; j < 0x17; j++)
+    {
+	printk(" r%2x=%2x",j,inb(tmport++));
+    }
+    tmport += 0x05;
+    printk(" r1c=%2x",inb(tmport));
+    tmport += 0x03;
+    printk(" r1f=%2x in_snd=%2x ",inb(tmport),in_snd[h]);
+    tmport++;
+    printk(" r20=%2x",inb(tmport));
+    tmport += 0x02;
+    printk(" r22=%2x \n",inb(tmport));
+    return (SCSI_ABORT_SNOOZE);
+}
+
+int atp870u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+{
+    unsigned char h;
+    /*
+     * See if a bus reset was suggested.
+     */
+/*    printk("atp870u_reset: \n");    */
+    for( h=0; h <= admaxu; h++ )
+    {
+       if ( SCpnt->host == atp_host[h] )
+       {
+	  goto find_host;
+       }
+    }
+    panic("Reset bus host not found !");
+find_host:
+/*    SCpnt->result = 0x00080000;
+    SCpnt->scsi_done(SCpnt);
+    workingu[h]=0;
+    quhdu[h]=0;
+    quendu[h]=0;
+    return (SCSI_RESET_SUCCESS | SCSI_RESET_BUS_RESET);  */
+    return (SCSI_RESET_SNOOZE);
+}
+
+const char *
+atp870u_info(struct Scsi_Host *notused)
+{
+  static char buffer[128];
+
+  strcpy(buffer, "ACARD AEC-6710/6712 PCI Ultra/W SCSI-3 Adapter Driver V1.0 ");
+
+  return buffer;
+}
+
+int
+atp870u_set_info(char *buffer, int length, struct Scsi_Host *HBAptr)
+{
+  return (-ENOSYS);  /* Currently this is a no-op */
+}
+
+#define BLS buffer + len + size
+int
+atp870u_proc_info(char *buffer, char **start, off_t offset, int length,
+    int hostno, int inout)
+{
+  struct Scsi_Host *HBAptr;
+  static u8 buff[512];
+  int	i;
+  int	size = 0;
+  int	len = 0;
+  off_t begin = 0;
+  off_t pos = 0;
+
+  HBAptr = NULL;
+  for (i = 0; i < 2; i++)
+  {
+    if ((HBAptr = atp_host[i]) != NULL)
+    {
+      if (HBAptr->host_no == hostno)
+      {
+	break;
+      }
+      HBAptr = NULL;
+    }
+  }
+
+  if (HBAptr == NULL)
+  {
+    size += sprintf(BLS, "Can't find adapter for host number %d\n", hostno);
+    len += size; pos = begin + len; size = 0;
+    goto stop_output;
+  }
+
+  if (inout == TRUE) /* Has data been written to the file? */
+  {
+    return (atp870u_set_info(buffer, length, HBAptr));
+  }
+
+  if (offset == 0)
+  {
+    memset(buff, 0, sizeof(buff));
+  }
+
+  size += sprintf(BLS, "ACARD AEC-671X Driver Version: 1.0\n");
+  len += size; pos = begin + len; size = 0;
+
+  size += sprintf(BLS, "\n");
+  size += sprintf(BLS, "Adapter Configuration:\n");
+  size += sprintf(BLS, "               Base IO: %#.4lx\n", HBAptr->io_port);
+  size += sprintf(BLS, "                   IRQ: %d\n", HBAptr->irq);
+  len += size; pos = begin + len; size = 0;
+
+stop_output:
+  *start = buffer + (offset - begin);	/* Start of wanted data */
+  len -= (offset - begin);	/* Start slop */
+  if (len > length)
+  {
+    len = length;		/* Ending slop */
+  }
+
+  return (len);
+}
+
+#include "sd.h"
+
+int atp870u_biosparam(Scsi_Disk * disk, kdev_t dev, int * ip)
+{
+  int heads, sectors, cylinders;
+
+  heads = 64;
+  sectors = 32;
+  cylinders = disk->capacity / (heads * sectors);
+
+  if ( cylinders > 1024 )
+  {
+    heads = 255;
+    sectors = 63;
+    cylinders = disk->capacity / (heads * sectors);
+  }
+
+  ip[0] = heads;
+  ip[1] = sectors;
+  ip[2] = cylinders;
+
+  return 0;
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = ATP870U;
+
+#include "scsi_module.c"
+#endif
+
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/atp870u.h linux/drivers/scsi/atp870u.h
--- v2.1.131/linux/drivers/scsi/atp870u.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/atp870u.h	Fri Dec 18 09:48:05 1998
@@ -0,0 +1,72 @@
+#ifndef _ATP870U_H
+
+/* $Id: atp870u.h,v 1.0 1997/05/07 15:09:00 root Exp root $
+ *
+ * Header file for the ACARD 870U/W driver for Linux
+ *
+ * $Log: atp870u.h,v $
+ * Revision 1.0  1997/05/07  15:09:00  root
+ * Initial revision
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kdev_t.h>
+
+/* I/O Port */
+
+#define MAX_CDB 12
+#define MAX_SENSE 14
+
+int atp870u_detect(Scsi_Host_Template *);
+int atp870u_command(Scsi_Cmnd *);
+int atp870u_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+int atp870u_abort(Scsi_Cmnd *);
+int atp870u_reset(Scsi_Cmnd *, unsigned int);
+int atp870u_biosparam(Disk *, kdev_t, int*);
+void send_s870(unsigned char);
+
+#define qcnt            32
+#define ATP870U_SCATTER 127
+#define ATP870U_CMDLUN 1
+
+#ifndef NULL
+        #define NULL 0
+#endif
+
+extern struct proc_dir_entry proc_scsi_atp870u;
+
+extern const char *atp870u_info(struct Scsi_Host *);
+
+extern int atp870u_proc_info(char *, char **, off_t, int, int, int);
+
+#define ATP870U {  						\
+	next:				NULL, 			\
+	module:				NULL, 			\
+	proc_dir:			&proc_scsi_atp870u,	\
+	proc_info:			atp870u_proc_info,      \
+	name:				NULL,			\
+	detect:                 	atp870u_detect,		\
+	release:               	 	NULL,                   \
+	info:                   	atp870u_info,           \
+	command:                	atp870u_command,	\
+        queuecommand:           	atp870u_queuecommand,	\
+        eh_strategy_handler: 		NULL,			\
+        eh_abort_handler: 		NULL,			\
+        eh_device_reset_handler:	NULL,			\
+        eh_bus_reset_handler:		NULL,			\
+        eh_host_reset_handler:		NULL,			\
+	abort:				atp870u_abort,          \
+	reset:				atp870u_reset,       	\
+	slave_attach:               	NULL,                   \
+	bios_param:                     atp870u_biosparam,	\
+	can_queue:                     	qcnt,                   \
+	this_id:                     	1,			\
+	sg_tablesize:                   ATP870U_SCATTER,        \
+	cmd_per_lun:                    ATP870U_CMDLUN,         \
+	present:                     	0,                      \
+	unchecked_isa_dma:              0,                      \
+	use_clustering:                 ENABLE_CLUSTERING,	\
+	use_new_eh_code:		0			\
+}
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/fd_mcs.c linux/drivers/scsi/fd_mcs.c
--- v2.1.131/linux/drivers/scsi/fd_mcs.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/fd_mcs.c	Fri Dec 18 10:12:25 1998
@@ -472,11 +472,9 @@
 	/* *************************************************** */	    
 #endif
 
-#if 0
 	/* IBM/ANSI scsi scan ordering */
 	/* Stick this back in when the scsi.c changes are there */
-	shpnt->reverse_scan = 1;
-#endif
+	shpnt->reverse_ordering = 1;
 	
 
 	/* saving info */
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/hosts.c linux/drivers/scsi/hosts.c
--- v2.1.131/linux/drivers/scsi/hosts.c	Thu Nov 12 16:21:21 1998
+++ linux/drivers/scsi/hosts.c	Fri Dec 18 10:12:25 1998
@@ -7,6 +7,8 @@
  *      Subsequent revisions: Eric Youngdale
  *
  *  <drew@colorado.edu>
+ *
+ *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  */
 
 
@@ -97,6 +99,18 @@
 #include "atari_scsi.h"
 #endif
 
+#ifdef CONFIG_MAC_SCSI_OLD
+#include "mac_scsi.h"
+#endif
+
+#ifdef CONFIG_MAC_SCSI
+#include "mac_scsinew.h"
+#endif
+
+#ifdef CONFIG_SCSI_MAC_ESP
+#include "mac_esp.h"
+#endif
+
 #ifdef CONFIG_SCSI_ADVANSYS
 #include "advansys.h"
 #endif
@@ -161,6 +175,10 @@
 #include "qlogicisp.h"
 #endif
 
+#ifdef CONFIG_SCSI_QLOGIC_FC
+#include "qlogicfc.h"
+#endif
+
 #ifdef CONFIG_SCSI_SEAGATE
 #include "seagate.h"
 #endif
@@ -189,6 +207,10 @@
 #include "wd7000.h"
 #endif
 
+#ifdef CONFIG_SCSI_MCA_53C9X
+#include "mca_53c9x.h"
+#endif
+
 #ifdef CONFIG_SCSI_IBMMCA
 #include "ibmmca.h"
 #endif
@@ -209,6 +231,14 @@
 #include "AM53C974.h"
 #endif
 
+#ifdef CONFIG_SCSI_MEGARAID
+#include "megaraid.h"
+#endif
+
+#ifdef CONFIG_SCSI_ACARD
+#include "atp870u.h"
+#endif
+
 #ifdef CONFIG_SCSI_SUNESP
 #include "esp.h"
 #endif
@@ -249,6 +279,10 @@
 #include "pluto.h"
 #endif
 
+#ifdef CONFIG_SCSI_INITIO
+#include "ini9100u.h"
+#endif
+
 #ifdef CONFIG_SCSI_DEBUG
 #include "scsi_debug.h"
 #endif
@@ -364,6 +398,18 @@
 #endif
 #endif
 
+#ifdef CONFIG_MAC
+#ifdef CONFIG_MAC_SCSI_OLD
+	MAC_SCSI,
+#endif
+#ifdef CONFIG_SCSI_MAC_ESP
+        SCSI_MAC_ESP,
+#endif
+#ifdef CONFIG_MAC_SCSI
+	MAC_NCR5380,
+#endif
+#endif
+
 #ifdef CONFIG_MVME16x_SCSI
 	MVME16x_SCSI,
 #endif
@@ -424,6 +470,9 @@
 #ifdef CONFIG_SCSI_QLOGIC_ISP
     QLOGICISP,
 #endif
+#ifdef CONFIG_SCSI_QLOGIC_FC
+    QLOGICFC,
+#endif
 #ifdef CONFIG_SCSI_PAS16
     MV_PAS16,
 #endif
@@ -451,6 +500,9 @@
 #ifdef CONFIG_SCSI_7000FASST
     WD7000,
 #endif
+#ifdef CONFIG_SCSI_MCA_53C9X
+    MCA_53C9X,
+#endif
 #ifdef CONFIG_SCSI_IBMMCA
     IBMMCA,
 #endif
@@ -463,12 +515,21 @@
 #ifdef CONFIG_SCSI_AM53C974
     AM53C974,
 #endif
+#ifdef CONFIG_SCSI_MEGARAID
+    MEGARAID,
+#endif
+#ifdef CONFIG_SCSI_ACARD
+    ATP870U,
+#endif
 #ifdef CONFIG_SCSI_SUNESP
     SCSI_SPARC_ESP,
 #endif
 #ifdef CONFIG_SCSI_GDTH
     GDTH,
 #endif
+#ifdef CONFIG_SCSI_INITIO
+    INI9100U,
+#endif
 #ifdef CONFIG_SCSI_QLOGICPTI
     QLOGICPTI,
 #endif
@@ -581,6 +642,7 @@
     next_scsi_host++;
     retval->host_queue = NULL;
     retval->host_wait = NULL;
+    retval->resetting = 0;
     retval->last_reset = 0;
     retval->irq = 0;
     retval->dma_channel = 0xff;
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/hosts.h linux/drivers/scsi/hosts.h
--- v2.1.131/linux/drivers/scsi/hosts.h	Fri Jul 31 17:07:58 1998
+++ linux/drivers/scsi/hosts.h	Tue Dec 22 10:46:17 1998
@@ -14,6 +14,8 @@
  *
  *  Further modified by Eric Youngdale to support multiple host adapters
  *  of the same type.
+ *
+ *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  */
 
 #ifndef _HOSTS_H
@@ -320,6 +322,7 @@
 /* public: */
     unsigned short extra_bytes;
     unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
+    int resetting; /* if set, it means that last_reset is a valid value */
     unsigned long last_reset;
 
 
@@ -379,7 +382,14 @@
      * Host has rejected a command because it was busy.
      */
     unsigned host_blocked:1;
+    
+    /*
+     * Host uses correct SCSI ordering not PC ordering. The bit is
+     * set for the minority of drivers whose authors actually read the spec ;)
+     */
 
+    unsigned reverse_ordering:1;
+    
     void (*select_queue_depths)(struct Scsi_Host *, Scsi_Device *);
 
     /*
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/i91uscsi.c linux/drivers/scsi/i91uscsi.c
--- v2.1.131/linux/drivers/scsi/i91uscsi.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/i91uscsi.c	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,2776 @@
+/**************************************************************************
+ * Initio 9100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
+ * 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: i91uscsi.c
+    Description: PCI I/F for INI-910 SCSI Bus Master Controller
+    Revision History:
+	11/09/94 Tim Chen, Initiali Version 0.90A
+	01/17/95 TC, release ver 1.01
+	02/09/95 TC  modify ReadPCIConfig, try both mechanisms;
+	02/15/95 TC  add support for INI-9100W
+	06/04/96 HC, Change to fit LINUX from jaspci.c
+	11/18/96 HC, Port for tulip
+	07/08/98 hc, Support 0002134A
+        07/23/98 wh, Change the abort_srb routine.
+	09/16/98 hl, Support ALPHA, Rewrite the returnNumberAdapters	<01>
+	12/09/98 bv, Removed unused code, changed tul_se2_wait to
+		     use udelay(30) and tul_do_pause to enable 
+		     interrupts for >= 2.1.95
+	12/13/98 bv, Use spinlocks instead of cli() for serialized
+		     access to HCS_Semaph, HCS_FirstAvail and HCS_LastAvail
+		     members of the HCS structure.
+**********************************************************************/
+
+#define DEBUG_INTERRUPT 0
+#define DEBUG_QUEUE     0
+#define DEBUG_STATE     0
+#define INT_DISC	0
+
+
+#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 <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/blk.h>
+#include <asm/io.h>
+
+#include "i91uscsi.h"
+
+/*--- external functions --*/
+static void tul_se2_wait(void);
+
+/*--- forward refrence ---*/
+static SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun);
+static SCB *tul_find_done_scb(HCS * pCurHcb);
+
+static int tulip_main(HCS * pCurHcb);
+
+static int tul_next_state(HCS * pCurHcb);
+static int tul_state_1(HCS * pCurHcb);
+static int tul_state_2(HCS * pCurHcb);
+static int tul_state_3(HCS * pCurHcb);
+static int tul_state_4(HCS * pCurHcb);
+static int tul_state_5(HCS * pCurHcb);
+static int tul_state_6(HCS * pCurHcb);
+static int tul_state_7(HCS * pCurHcb);
+static int tul_xfer_data_in(HCS * pCurHcb);
+static int tul_xfer_data_out(HCS * pCurHcb);
+static int tul_xpad_in(HCS * pCurHcb);
+static int tul_xpad_out(HCS * pCurHcb);
+static int tul_status_msg(HCS * pCurHcb);
+
+static int tul_msgin(HCS * pCurHcb);
+static int tul_msgin_sync(HCS * pCurHcb);
+static int tul_msgin_accept(HCS * pCurHcb);
+static int tul_msgout_reject(HCS * pCurHcb);
+static int tul_msgin_extend(HCS * pCurHcb);
+
+static int tul_msgout_ide(HCS * pCurHcb);
+static int tul_msgout_abort_targ(HCS * pCurHcb);
+static int tul_msgout_abort_tag(HCS * pCurHcb);
+
+static int tul_bus_device_reset(HCS * pCurHcb);
+static void tul_select_atn(HCS * pCurHcb, SCB * pCurScb);
+static void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb);
+static void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb);
+static int int_tul_busfree(HCS * pCurHcb);
+int int_tul_scsi_rst(HCS * pCurHcb);
+static int int_tul_bad_seq(HCS * pCurHcb);
+static int int_tul_resel(HCS * pCurHcb);
+static int tul_sync_done(HCS * pCurHcb);
+static int wdtr_done(HCS * pCurHcb);
+static int wait_tulip(HCS * pCurHcb);
+static int tul_wait_done_disc(HCS * pCurHcb);
+static int tul_wait_disc(HCS * pCurHcb);
+static void tulip_scsi(HCS * pCurHcb);
+static int tul_post_scsi_rst(HCS * pCurHcb);
+
+static void tul_se2_ew_en(WORD CurBase);
+static void tul_se2_ew_ds(WORD CurBase);
+static int tul_se2_rd_all(WORD CurBase);
+static void tul_se2_update_all(WORD CurBase);	/* setup default pattern */
+static void tul_read_eeprom(WORD CurBase);
+
+				/* ---- EXTERNAL VARIABLES ---- */
+HCS tul_hcs[MAX_SUPPORTED_ADAPTERS];
+				/* ---- INTERNAL VARIABLES ---- */
+static INI_ADPT_STRUCT i91u_adpt[MAX_SUPPORTED_ADAPTERS];
+
+/*NVRAM nvram, *nvramp = &nvram; */
+static NVRAM i91unvram;
+static NVRAM *i91unvramp;
+
+
+
+static UCHAR i91udftNvRam[64] =
+{
+/*----------- header -----------*/
+	0x25, 0xc9,		/* Signature    */
+	0x40,			/* Size         */
+	0x01,			/* Revision     */
+	/* -- Host Adapter Structure -- */
+	0x95,			/* ModelByte0   */
+	0x00,			/* ModelByte1   */
+	0x00,			/* ModelInfo    */
+	0x01,			/* NumOfCh      */
+	NBC1_DEFAULT,		/* BIOSConfig1  */
+	0,			/* BIOSConfig2  */
+	0,			/* HAConfig1    */
+	0,			/* HAConfig2    */
+	/* SCSI channel 0 and target Structure  */
+	7,			/* SCSIid       */
+	NCC1_DEFAULT,		/* SCSIconfig1  */
+	0,			/* SCSIconfig2  */
+	0x10,			/* NumSCSItarget */
+
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+
+	/* SCSI channel 1 and target Structure  */
+	7,			/* SCSIid       */
+	NCC1_DEFAULT,		/* SCSIconfig1  */
+	0,			/* SCSIconfig2  */
+	0x10,			/* NumSCSItarget */
+
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT, NTC_DEFAULT,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0};			/*      - CheckSum -            */
+
+
+static UCHAR tul_rate_tbl[8] =	/* fast 20      */
+{
+				/* nanosecond devide by 4 */
+	12,			/* 50ns,  20M   */
+	18,			/* 75ns,  13.3M */
+	25,			/* 100ns, 10M   */
+	31,			/* 125ns, 8M    */
+	37,			/* 150ns, 6.6M  */
+	43,			/* 175ns, 5.7M  */
+	50,			/* 200ns, 5M    */
+	62			/* 250ns, 4M    */
+};
+
+extern int tul_num_ch;
+
+
+static void tul_do_pause(unsigned amount)
+{				/* Pause for amount*10 milliseconds */
+	unsigned long the_time = jiffies + amount;	/* 0.01 seconds per jiffy */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	/*
+	 * We need to release the io_request_lock 
+	 * to make sure that the jiffies are updated
+	 */
+	spin_unlock_irq(&io_request_lock);
+
+	while (time_before_eq(jiffies, the_time));
+
+	/*
+	 * Acquire the io_request_lock again
+	 */
+	spin_lock_irq(&io_request_lock);
+#else
+	while (jiffies < the_time);
+#endif
+}
+
+/*-- forward reference --*/
+
+/*******************************************************************
+	Use memeory refresh time        ~ 15us * 2
+********************************************************************/
+void tul_se2_wait()
+{
+#if 1
+	udelay(30);
+#else
+	UCHAR readByte;
+
+	readByte = TUL_RD(0, 0x61);
+	if ((readByte & 0x10) == 0x10) {
+		for (;;) {
+			readByte = TUL_RD(0, 0x61);
+			if ((readByte & 0x10) == 0x10)
+				break;
+		}
+		for (;;) {
+			readByte = TUL_RD(0, 0x61);
+			if ((readByte & 0x10) != 0x10)
+				break;
+		}
+	} else {
+		for (;;) {
+			readByte = TUL_RD(0, 0x61);
+			if ((readByte & 0x10) == 0x10)
+				break;
+		}
+		for (;;) {
+			readByte = TUL_RD(0, 0x61);
+			if ((readByte & 0x10) != 0x10)
+				break;
+		}
+	}
+#endif
+}
+
+
+/******************************************************************
+ Input: instruction for  Serial E2PROM
+
+ EX: se2_rd(0 call se2_instr() to send address and read command
+
+	 StartBit  OP_Code   Address                Data
+	 --------- --------  ------------------     -------
+	 1         1 , 0     A5,A4,A3,A2,A1,A0      D15-D0
+
+		 +-----------------------------------------------------
+		 |
+ CS -----+
+			+--+  +--+  +--+  +--+  +--+
+			^  |  ^  |  ^  |  ^  |  ^  |
+			|  |  |  |  |  |  |  |  |  |
+ CLK -------+  +--+  +--+  +--+  +--+  +--
+ (leading edge trigger)
+
+		 +--1-----1--+
+		 | SB    OP  |  OP    A5    A4
+ DI  ----+           +--0------------------
+ (address and cmd sent to nvram)
+
+	 -------------------------------------------+
+												|
+ DO                                             +---
+ (data sent from nvram)
+
+
+******************************************************************/
+void tul_se2_instr(WORD CurBase, UCHAR instr)
+{
+	int i;
+	UCHAR b;
+
+	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* cs+start bit */
+	tul_se2_wait();
+	TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK | SE2DO);	/* +CLK */
+	tul_se2_wait();
+
+	for (i = 0; i < 8; i++) {
+		if (instr & 0x80)
+			b = SE2CS | SE2DO;	/* -CLK+dataBit */
+		else
+			b = SE2CS;	/* -CLK */
+		TUL_WR(CurBase + TUL_NVRAM, b);
+		tul_se2_wait();
+		TUL_WR(CurBase + TUL_NVRAM, b | SE2CLK);	/* +CLK */
+		tul_se2_wait();
+		instr <<= 1;
+	}
+	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
+	tul_se2_wait();
+	return;
+}
+
+
+/******************************************************************
+ Function name  : tul_se2_ew_en
+ Description    : Enable erase/write state of serial EEPROM
+******************************************************************/
+void tul_se2_ew_en(WORD CurBase)
+{
+	tul_se2_instr(CurBase, 0x30);	/* EWEN */
+	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
+	tul_se2_wait();
+	return;
+}
+
+
+/************************************************************************
+ Disable erase/write state of serial EEPROM
+*************************************************************************/
+void tul_se2_ew_ds(WORD CurBase)
+{
+	tul_se2_instr(CurBase, 0);	/* EWDS */
+	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
+	tul_se2_wait();
+	return;
+}
+
+
+/******************************************************************
+	Input  :address of Serial E2PROM
+	Output :value stored in  Serial E2PROM
+*******************************************************************/
+USHORT tul_se2_rd(WORD CurBase, ULONG adr)
+{
+	UCHAR instr, readByte;
+	USHORT readWord;
+	int i;
+
+	instr = (UCHAR) (adr | 0x80);
+	tul_se2_instr(CurBase, instr);	/* READ INSTR */
+	readWord = 0;
+
+	for (i = 15; i >= 0; i--) {
+		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
+		tul_se2_wait();
+		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
+
+		/* sample data after the following edge of clock  */
+		readByte = TUL_RD(CurBase, TUL_NVRAM);
+		readByte &= SE2DI;
+		readWord += (readByte << i);
+		tul_se2_wait();	/* 6/20/95 */
+	}
+
+	TUL_WR(CurBase + TUL_NVRAM, 0);		/* no chip select */
+	tul_se2_wait();
+	return readWord;
+}
+
+
+/******************************************************************
+ Input: new value in  Serial E2PROM, address of Serial E2PROM
+*******************************************************************/
+void tul_se2_wr(WORD CurBase, UCHAR adr, USHORT writeWord)
+{
+	UCHAR readByte;
+	UCHAR instr;
+	int i;
+
+	instr = (UCHAR) (adr | 0x40);
+	tul_se2_instr(CurBase, instr);	/* WRITE INSTR */
+	for (i = 15; i >= 0; i--) {
+		if (writeWord & 0x8000)
+			TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2DO);	/* -CLK+dataBit 1 */
+		else
+			TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK+dataBit 0 */
+		tul_se2_wait();
+		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
+		tul_se2_wait();
+		writeWord <<= 1;
+	}
+	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
+	tul_se2_wait();
+	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS  */
+	tul_se2_wait();
+
+	TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* +CS  */
+	tul_se2_wait();
+
+	for (;;) {
+		TUL_WR(CurBase + TUL_NVRAM, SE2CS | SE2CLK);	/* +CLK */
+		tul_se2_wait();
+		TUL_WR(CurBase + TUL_NVRAM, SE2CS);	/* -CLK */
+		tul_se2_wait();
+		if ((readByte = TUL_RD(CurBase, TUL_NVRAM)) & SE2DI)
+			break;	/* write complete */
+	}
+	TUL_WR(CurBase + TUL_NVRAM, 0);		/* -CS */
+	return;
+}
+
+
+/***********************************************************************
+ Read SCSI H/A configuration parameters from serial EEPROM
+************************************************************************/
+int tul_se2_rd_all(WORD CurBase)
+{
+	int i;
+	ULONG chksum = 0;
+	USHORT *np;
+
+	i91unvramp = &i91unvram;
+	np = (USHORT *) i91unvramp;
+	for (i = 0; i < 32; i++) {
+		*np++ = tul_se2_rd(CurBase, i);
+	}
+
+/*--------------------Is signature "ini" ok ? ----------------*/
+	if (i91unvramp->NVM_Signature != INI_SIGNATURE)
+		return -1;
+/*---------------------- Is ckecksum ok ? ----------------------*/
+	np = (USHORT *) i91unvramp;
+	for (i = 0; i < 31; i++)
+		chksum += *np++;
+	if (i91unvramp->NVM_CheckSum != (USHORT) chksum)
+		return -1;
+	return 1;
+}
+
+
+/***********************************************************************
+ Update SCSI H/A configuration parameters from serial EEPROM
+************************************************************************/
+void tul_se2_update_all(WORD CurBase)
+{				/* setup default pattern */
+	int i;
+	ULONG chksum = 0;
+	USHORT *np, *np1;
+
+	i91unvramp = &i91unvram;
+	/* Calculate checksum first */
+	np = (USHORT *) i91udftNvRam;
+	for (i = 0; i < 31; i++)
+		chksum += *np++;
+	*np = (USHORT) chksum;
+	tul_se2_ew_en(CurBase);	/* Enable write  */
+
+	np = (USHORT *) i91udftNvRam;
+	np1 = (USHORT *) i91unvramp;
+	for (i = 0; i < 32; i++, np++, np1++) {
+		if (*np != *np1) {
+			tul_se2_wr(CurBase, i, *np);
+		}
+	}
+
+	tul_se2_ew_ds(CurBase);	/* Disable write   */
+	return;
+}
+
+/*************************************************************************
+ Function name  : read_eeprom
+**************************************************************************/
+void tul_read_eeprom(WORD CurBase)
+{
+	UCHAR gctrl;
+
+	i91unvramp = &i91unvram;
+/*------Enable EEProm programming ---*/
+	gctrl = TUL_RD(CurBase, TUL_GCTRL);
+	TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT);
+	if (tul_se2_rd_all(CurBase) != 1) {
+		tul_se2_update_all(CurBase);	/* setup default pattern */
+		tul_se2_rd_all(CurBase);	/* load again  */
+	}
+/*------ Disable EEProm programming ---*/
+	gctrl = TUL_RD(CurBase, TUL_GCTRL);
+	TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);
+}				/* read_eeprom */
+
+int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt,
+			       BYTE bBus, BYTE bDevice)
+{
+	int i, j;
+
+	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {
+		if (i91u_adpt[i].ADPT_BIOS < wBIOS)
+			continue;
+		if (i91u_adpt[i].ADPT_BIOS == wBIOS) {
+			if (i91u_adpt[i].ADPT_BASE == wBASE)
+				if (i91u_adpt[i].ADPT_Bus != 0xFF)
+					return (FAILURE);
+				else if (i91u_adpt[i].ADPT_BASE < wBASE)
+					continue;
+		}
+		for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) {
+			i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE;
+			i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR;
+			i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS;
+			i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus;
+			i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device;
+		}
+		i91u_adpt[i].ADPT_BASE = wBASE;
+		i91u_adpt[i].ADPT_INTR = bInterrupt;
+		i91u_adpt[i].ADPT_BIOS = wBIOS;
+		i91u_adpt[i].ADPT_Bus = bBus;
+		i91u_adpt[i].ADPT_Device = bDevice;
+		return (SUCCESSFUL);
+	}
+	return (FAILURE);
+}
+
+void init_i91uAdapter_table(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) {	/* Initialize adapter structure */
+		i91u_adpt[i].ADPT_BIOS = 0xffff;
+		i91u_adpt[i].ADPT_BASE = 0xffff;
+		i91u_adpt[i].ADPT_INTR = 0xff;
+		i91u_adpt[i].ADPT_Bus = 0xff;
+		i91u_adpt[i].ADPT_Device = 0xff;
+	}
+	return;
+}
+
+void tul_stop_bm(HCS * pCurHcb)
+{
+
+	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
+		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+		/* wait Abort DMA xfer done */
+		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+}
+
+/***************************************************************************/
+void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx)
+{
+	pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE;	/* Supply base address  */
+	pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS;	/* Supply BIOS address  */
+	pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR;	/* Supply interrupt line */
+	return;
+}
+
+/***************************************************************************/
+int tul_reset_scsi(HCS * pCurHcb, int seconds)
+{
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS);
+
+	while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT));
+	/* reset tulip chip */
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0);
+
+	/* Stall for a while, wait for target's firmware ready,make it 2 sec ! */
+	/* SONY 5200 tape drive won't work if only stall for 1 sec */
+	tul_do_pause(seconds * 100);
+
+	TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+
+	return (SCSI_RESET_SUCCESS);
+}
+
+/***************************************************************************/
+int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds)
+{
+	int i;
+	WORD *pwFlags;
+	BYTE *pbHeads;
+	SCB *pTmpScb, *pPrevScb = NULL;
+
+	pCurHcb->HCS_NumScbs = tul_num_scb;
+	pCurHcb->HCS_Semaph = 1;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	pCurHcb->HCS_SemaphLock = SPIN_LOCK_UNLOCKED;
+#endif
+	pCurHcb->HCS_JSStatus0 = 0;
+	pCurHcb->HCS_Scb = scbp;
+	pCurHcb->HCS_NxtPend = scbp;
+	pCurHcb->HCS_NxtAvail = scbp;
+	for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) {
+		pTmpScb->SCB_TagId = i;
+		if (i != 0)
+			pPrevScb->SCB_NxtScb = pTmpScb;
+		pPrevScb = pTmpScb;
+	}
+	pPrevScb->SCB_NxtScb = NULL;
+	pCurHcb->HCS_ScbEnd = pTmpScb;
+	pCurHcb->HCS_FirstAvail = scbp;
+	pCurHcb->HCS_LastAvail = pPrevScb;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	pCurHcb->HCS_AvailLock = SPIN_LOCK_UNLOCKED;
+#endif
+	pCurHcb->HCS_FirstPend = NULL;
+	pCurHcb->HCS_LastPend = NULL;
+	pCurHcb->HCS_FirstBusy = NULL;
+	pCurHcb->HCS_LastBusy = NULL;
+	pCurHcb->HCS_FirstDone = NULL;
+	pCurHcb->HCS_LastDone = NULL;
+	pCurHcb->HCS_ActScb = NULL;
+	pCurHcb->HCS_ActTcs = NULL;
+
+	tul_read_eeprom(pCurHcb->HCS_Base);
+/*---------- get H/A configuration -------------*/
+	if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8)
+		pCurHcb->HCS_MaxTar = 8;
+	else
+		pCurHcb->HCS_MaxTar = 16;
+
+	pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1;
+
+	pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID;
+	pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);
+
+#if CHK_PARITY
+	/* Enable parity error response */
+	TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);
+#endif
+
+	/* Mask all the interrupt       */
+	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+
+	tul_stop_bm(pCurHcb);
+	/* --- Initialize the tulip --- */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP);
+
+	/* program HBA's SCSI ID        */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4);
+
+	/* Enable Initiator Mode ,phase latch,alternate sync period mode,
+	   disable SCSI reset */
+	if (pCurHcb->HCS_Config & HCC_EN_PAR)
+		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR);
+	else
+		pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1);
+
+	/* Enable HW reselect           */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0);
+
+	/* selection time out = 250 ms */
+	TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);
+
+/*--------- Enable SCSI terminator -----*/
+	TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2)));
+	TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1,
+	       ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE));
+
+	for (i = 0,
+	     pwFlags = (WORD *) & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config),
+	     pbHeads = pbBiosAdr + 0x180;
+	     i < pCurHcb->HCS_MaxTar;
+	     i++, pwFlags++) {
+		pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+		if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255)
+			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+		else
+			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
+		pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0;
+		pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1;
+		pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++;
+		if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255)
+			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63;
+		else
+			pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0;
+		pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++;
+		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;
+		pCurHcb->HCS_ActTags[i] = 0;
+		pCurHcb->HCS_MaxTags[i] = 0xFF;
+	}			/* for                          */
+	printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n",
+	       pCurHcb->HCS_Base, pCurHcb->HCS_Intr,
+	       pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);
+/*------------------- reset SCSI Bus ---------------------------*/
+	if (pCurHcb->HCS_Config & HCC_SCSI_RESET) {
+		printk("i91u: Reset SCSI Bus ... \n");
+		tul_reset_scsi(pCurHcb, seconds);
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9);
+	return (0);
+}
+
+/***************************************************************************/
+SCB *tul_alloc_scb(HCS * hcsp)
+{
+	SCB *pTmpScb;
+	ULONG flags;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+	if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {
+#if DEBUG_QUEUE
+		printk("find scb at %08lx\n", (ULONG) pTmpScb);
+#endif
+		if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL)
+			hcsp->HCS_LastAvail = NULL;
+		pTmpScb->SCB_NxtScb = NULL;
+		pTmpScb->SCB_Status = SCB_RENT;
+	}
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return (pTmpScb);
+}
+
+/***************************************************************************/
+void tul_release_scb(HCS * hcsp, SCB * scbp)
+{
+	ULONG flags;
+
+#if DEBUG_QUEUE
+	printk("Release SCB %lx; ", (ULONG) scbp);
+#endif
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+	scbp->SCB_Srb = 0;
+	scbp->SCB_Status = 0;
+	scbp->SCB_NxtScb = NULL;
+	if (hcsp->HCS_LastAvail != NULL) {
+		hcsp->HCS_LastAvail->SCB_NxtScb = scbp;
+		hcsp->HCS_LastAvail = scbp;
+	} else {
+		hcsp->HCS_FirstAvail = scbp;
+		hcsp->HCS_LastAvail = scbp;
+	}
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);
+#else
+	restore_flags(flags);
+#endif
+}
+
+/***************************************************************************/
+void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+	printk("Append pend SCB %lx; ", (ULONG) scbp);
+#endif
+	scbp->SCB_Status = SCB_PEND;
+	scbp->SCB_NxtScb = NULL;
+	if (pCurHcb->HCS_LastPend != NULL) {
+		pCurHcb->HCS_LastPend->SCB_NxtScb = scbp;
+		pCurHcb->HCS_LastPend = scbp;
+	} else {
+		pCurHcb->HCS_FirstPend = scbp;
+		pCurHcb->HCS_LastPend = scbp;
+	}
+}
+
+/***************************************************************************/
+void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+	printk("Push pend SCB %lx; ", (ULONG) scbp);
+#endif
+	scbp->SCB_Status = SCB_PEND;
+	if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) {
+		pCurHcb->HCS_FirstPend = scbp;
+	} else {
+		pCurHcb->HCS_FirstPend = scbp;
+		pCurHcb->HCS_LastPend = scbp;
+	}
+}
+
+/***************************************************************************/
+SCB *tul_find_first_pend_scb(HCS * pCurHcb)
+{
+	SCB *pFirstPend;
+
+
+	pFirstPend = pCurHcb->HCS_FirstPend;
+	while (pFirstPend != NULL) {
+		if (pFirstPend->SCB_Opcode != ExecSCSI) {
+			return (pFirstPend);
+		}
+		if (pFirstPend->SCB_TagMsg == 0) {
+			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) &&
+			    !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
+				return (pFirstPend);
+			}
+		} else {
+			if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >=
+			  pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) |
+			    (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) {
+				pFirstPend = pFirstPend->SCB_NxtScb;
+				continue;
+			}
+			return (pFirstPend);
+		}
+		pFirstPend = pFirstPend->SCB_NxtScb;
+	}
+
+
+	return (pFirstPend);
+}
+/***************************************************************************/
+SCB *tul_pop_pend_scb(HCS * pCurHcb)
+{
+	SCB *pTmpScb;
+
+	if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) {
+		if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
+			pCurHcb->HCS_LastPend = NULL;
+		pTmpScb->SCB_NxtScb = NULL;
+	}
+#if DEBUG_QUEUE
+	printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);
+#endif
+	return (pTmpScb);
+}
+
+
+/***************************************************************************/
+void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb)
+{
+	SCB *pTmpScb, *pPrevScb;
+
+#if DEBUG_QUEUE
+	printk("unlink pend SCB %lx; ", (ULONG) pCurScb);
+#endif
+
+	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;
+	while (pTmpScb != NULL) {
+		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
+			if (pTmpScb == pCurHcb->HCS_FirstPend) {
+				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
+					pCurHcb->HCS_LastPend = NULL;
+			} else {
+				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+				if (pTmpScb == pCurHcb->HCS_LastPend)
+					pCurHcb->HCS_LastPend = pPrevScb;
+			}
+			pTmpScb->SCB_NxtScb = NULL;
+			break;
+		}
+		pPrevScb = pTmpScb;
+		pTmpScb = pTmpScb->SCB_NxtScb;
+	}
+	return;
+}
+/***************************************************************************/
+void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+	printk("append busy SCB %lx; ", (ULONG) scbp);
+#endif
+	if (scbp->SCB_TagMsg)
+		pCurHcb->HCS_ActTags[scbp->SCB_Target]++;
+	else
+		pCurHcb->HCS_Tcs[scbp->SCB_Target].TCS_Flags |= TCF_BUSY;
+	scbp->SCB_Status = SCB_BUSY;
+	scbp->SCB_NxtScb = NULL;
+	if (pCurHcb->HCS_LastBusy != NULL) {
+		pCurHcb->HCS_LastBusy->SCB_NxtScb = scbp;
+		pCurHcb->HCS_LastBusy = scbp;
+	} else {
+		pCurHcb->HCS_FirstBusy = scbp;
+		pCurHcb->HCS_LastBusy = scbp;
+	}
+}
+
+/***************************************************************************/
+SCB *tul_pop_busy_scb(HCS * pCurHcb)
+{
+	SCB *pTmpScb;
+
+
+	if ((pTmpScb = pCurHcb->HCS_FirstBusy) != NULL) {
+		if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+			pCurHcb->HCS_LastBusy = NULL;
+		pTmpScb->SCB_NxtScb = NULL;
+		if (pTmpScb->SCB_TagMsg)
+			pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+		else
+			pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+	}
+#if DEBUG_QUEUE
+	printk("Pop busy SCB %lx; ", (ULONG) pTmpScb);
+#endif
+	return (pTmpScb);
+}
+
+/***************************************************************************/
+void tul_unlink_busy_scb(HCS * pCurHcb, SCB * pCurScb)
+{
+	SCB *pTmpScb, *pPrevScb;
+
+#if DEBUG_QUEUE
+	printk("unlink busy SCB %lx; ", (ULONG) pCurScb);
+#endif
+
+	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
+	while (pTmpScb != NULL) {
+		if (pCurScb == pTmpScb) {	/* Unlink this SCB              */
+			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
+				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+					pCurHcb->HCS_LastBusy = NULL;
+			} else {
+				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+				if (pTmpScb == pCurHcb->HCS_LastBusy)
+					pCurHcb->HCS_LastBusy = pPrevScb;
+			}
+			pTmpScb->SCB_NxtScb = NULL;
+			if (pTmpScb->SCB_TagMsg)
+				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+			else
+				pCurHcb->HCS_Tcs[pTmpScb->SCB_Target].TCS_Flags &= ~TCF_BUSY;
+			break;
+		}
+		pPrevScb = pTmpScb;
+		pTmpScb = pTmpScb->SCB_NxtScb;
+	}
+	return;
+}
+
+/***************************************************************************/
+SCB *tul_find_busy_scb(HCS * pCurHcb, WORD tarlun)
+{
+	SCB *pTmpScb, *pPrevScb;
+	WORD scbp_tarlun;
+
+
+	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;
+	while (pTmpScb != NULL) {
+		scbp_tarlun = (pTmpScb->SCB_Lun << 8) | (pTmpScb->SCB_Target);
+		if (scbp_tarlun == tarlun) {	/* Unlink this SCB              */
+			break;
+		}
+		pPrevScb = pTmpScb;
+		pTmpScb = pTmpScb->SCB_NxtScb;
+	}
+#if DEBUG_QUEUE
+	printk("find busy SCB %lx; ", (ULONG) pTmpScb);
+#endif
+	return (pTmpScb);
+}
+
+/***************************************************************************/
+void tul_append_done_scb(HCS * pCurHcb, SCB * scbp)
+{
+
+#if DEBUG_QUEUE
+	printk("append done SCB %lx; ", (ULONG) scbp);
+#endif
+
+	scbp->SCB_Status = SCB_DONE;
+	scbp->SCB_NxtScb = NULL;
+	if (pCurHcb->HCS_LastDone != NULL) {
+		pCurHcb->HCS_LastDone->SCB_NxtScb = scbp;
+		pCurHcb->HCS_LastDone = scbp;
+	} else {
+		pCurHcb->HCS_FirstDone = scbp;
+		pCurHcb->HCS_LastDone = scbp;
+	}
+}
+
+/***************************************************************************/
+SCB *tul_find_done_scb(HCS * pCurHcb)
+{
+	SCB *pTmpScb;
+
+
+	if ((pTmpScb = pCurHcb->HCS_FirstDone) != NULL) {
+		if ((pCurHcb->HCS_FirstDone = pTmpScb->SCB_NxtScb) == NULL)
+			pCurHcb->HCS_LastDone = NULL;
+		pTmpScb->SCB_NxtScb = NULL;
+	}
+#if DEBUG_QUEUE
+	printk("find done SCB %lx; ", (ULONG) pTmpScb);
+#endif
+	return (pTmpScb);
+}
+
+/***************************************************************************/
+int tul_abort_srb(HCS * pCurHcb, ULONG srbp)
+{
+	ULONG flags;
+	SCB *pTmpScb, *pPrevScb;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+
+	if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
+		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+		/* disable Jasmin SCSI Int        */
+		tulip_main(pCurHcb);
+
+		pCurHcb->HCS_Semaph = 1;
+		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+		restore_flags(flags);
+#endif
+
+		return SCSI_ABORT_SNOOZE;
+	}
+	pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend;	/* Check Pend queue */
+	while (pTmpScb != NULL) {
+		/* 07/27/98 */
+		if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
+			if (pTmpScb == pCurHcb->HCS_ActScb) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+				restore_flags(flags);
+#endif
+				return SCSI_ABORT_BUSY;
+			} else if (pTmpScb == pCurHcb->HCS_FirstPend) {
+				if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL)
+					pCurHcb->HCS_LastPend = NULL;
+			} else {
+				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+				if (pTmpScb == pCurHcb->HCS_LastPend)
+					pCurHcb->HCS_LastPend = pPrevScb;
+			}
+			pTmpScb->SCB_HaStat = HOST_ABORTED;
+			pTmpScb->SCB_Flags |= SCF_DONE;
+			if (pTmpScb->SCB_Flags & SCF_POST)
+				(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+			restore_flags(flags);
+#endif
+			return SCSI_ABORT_SUCCESS;
+		}
+		pPrevScb = pTmpScb;
+		pTmpScb = pTmpScb->SCB_NxtScb;
+	}
+
+	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
+	while (pTmpScb != NULL) {
+
+		if (pTmpScb->SCB_Srb == (unsigned char *) srbp) {
+
+			if (pTmpScb == pCurHcb->HCS_ActScb) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+				restore_flags(flags);
+#endif
+				return SCSI_ABORT_BUSY;
+			} else if (pTmpScb->SCB_TagMsg == 0) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+				restore_flags(flags);
+#endif
+				return SCSI_ABORT_BUSY;
+			} else {
+				pCurHcb->HCS_ActTags[pTmpScb->SCB_Target]--;
+				if (pTmpScb == pCurHcb->HCS_FirstBusy) {
+					if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+						pCurHcb->HCS_LastBusy = NULL;
+				} else {
+					pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+					if (pTmpScb == pCurHcb->HCS_LastBusy)
+						pCurHcb->HCS_LastBusy = pPrevScb;
+				}
+				pTmpScb->SCB_NxtScb = NULL;
+
+
+				pTmpScb->SCB_HaStat = HOST_ABORTED;
+				pTmpScb->SCB_Flags |= SCF_DONE;
+				if (pTmpScb->SCB_Flags & SCF_POST)
+					(*pTmpScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pTmpScb);
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+				spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+				restore_flags(flags);
+#endif
+				return SCSI_ABORT_SUCCESS;
+			}
+		}
+		pPrevScb = pTmpScb;
+		pTmpScb = pTmpScb->SCB_NxtScb;
+	}
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return (SCSI_ABORT_NOT_RUNNING);
+}
+
+/***************************************************************************/
+int tul_bad_seq(HCS * pCurHcb)
+{
+	SCB *pCurScb;
+
+	printk("tul_bad_seg c=%d\n", pCurHcb->HCS_Index);
+
+	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
+		tul_unlink_busy_scb(pCurHcb, pCurScb);
+		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+		pCurScb->SCB_TaStat = 0;
+		tul_append_done_scb(pCurHcb, pCurScb);
+	}
+	tul_stop_bm(pCurHcb);
+
+	tul_reset_scsi(pCurHcb, 8);	/* 7/29/98 */
+
+	return (tul_post_scsi_rst(pCurHcb));
+}
+
+/************************************************************************/
+int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags)
+{
+	ULONG flags;
+	SCB *pScb;
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+
+	if (ResetFlags & SCSI_RESET_ASYNCHRONOUS) {
+
+		if ((pCurHcb->HCS_Semaph == 0) && (pCurHcb->HCS_ActScb == NULL)) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+			/* disable Jasmin SCSI Int        */
+			tulip_main(pCurHcb);
+
+			pCurHcb->HCS_Semaph = 1;
+			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+			restore_flags(flags);
+#endif
+
+			return SCSI_RESET_SNOOZE;
+		}
+		pScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
+		while (pScb != NULL) {
+			if (pScb->SCB_Srb == (unsigned char *) pSrb)
+				break;
+			pScb = pScb->SCB_NxtScb;
+		}
+		if (pScb == NULL) {
+			printk("Unable to Reset - No SCB Found\n");
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+			spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+			restore_flags(flags);
+#endif
+			return SCSI_RESET_NOT_RUNNING;
+		}
+	}
+	if ((pScb = tul_alloc_scb(pCurHcb)) == NULL) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+		spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+		restore_flags(flags);
+#endif
+		return SCSI_RESET_NOT_RUNNING;
+	}
+	pScb->SCB_Opcode = BusDevRst;
+	pScb->SCB_Flags = SCF_POST;
+	pScb->SCB_Target = target;
+	pScb->SCB_Mode = 0;
+
+	pScb->SCB_Srb = 0;
+	if (ResetFlags & SCSI_RESET_SYNCHRONOUS) {
+		pScb->SCB_Srb = (unsigned char *) pSrb;
+	}
+	tul_push_pend_scb(pCurHcb, pScb);	/* push this SCB to Pending queue */
+
+	if (pCurHcb->HCS_Semaph == 1) {
+		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+		/* disable Jasmin SCSI Int        */
+		pCurHcb->HCS_Semaph = 0;
+
+		tulip_main(pCurHcb);
+
+		pCurHcb->HCS_Semaph = 1;
+		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+	}
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return SCSI_RESET_PENDING;
+}
+
+int tul_reset_scsi_bus(HCS * pCurHcb)
+{
+	ULONG flags;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+	pCurHcb->HCS_Semaph = 0;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	restore_flags(flags);
+#endif
+
+	tul_stop_bm(pCurHcb);
+
+	tul_reset_scsi(pCurHcb, 2);	/* 7/29/98 */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+	tul_post_scsi_rst(pCurHcb);
+
+	tulip_main(pCurHcb);
+
+	pCurHcb->HCS_Semaph = 1;
+	TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return (SCSI_RESET_SUCCESS | SCSI_RESET_HOST_RESET);
+}
+
+/************************************************************************/
+void tul_exec_scb(HCS * pCurHcb, SCB * pCurScb)
+{
+	ULONG flags;
+
+	pCurScb->SCB_Mode = 0;
+
+	pCurScb->SCB_SGIdx = 0;
+	pCurScb->SCB_SGMax = pCurScb->SCB_SGLen;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	save_flags(flags);
+	cli();
+#endif
+
+	tul_append_pend_scb(pCurHcb, pCurScb);	/* Append this SCB to Pending queue */
+
+/* VVVVV 07/21/98 */
+	if (pCurHcb->HCS_Semaph == 1) {
+		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+		/* disable Jasmin SCSI Int        */
+		pCurHcb->HCS_Semaph = 0;
+
+		tulip_main(pCurHcb);
+
+		pCurHcb->HCS_Semaph = 1;
+		TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+	}
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&(pCurHcb->HCS_SemaphLock), flags);
+#else
+	restore_flags(flags);
+#endif
+	return;
+}
+
+/***************************************************************************/
+int tul_isr(HCS * pCurHcb)
+{
+	/* Enter critical section       */
+
+	if (TUL_RD(pCurHcb->HCS_Base, TUL_Int) & TSS_INT_PENDING) {
+		if (pCurHcb->HCS_Semaph == 1) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F);
+			/* Disable Tulip SCSI Int */
+			pCurHcb->HCS_Semaph = 0;
+
+			tulip_main(pCurHcb);
+
+			pCurHcb->HCS_Semaph = 1;
+			TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x0F);
+			return (1);
+		}
+	}
+	return (0);
+}
+
+/***************************************************************************/
+int tulip_main(HCS * pCurHcb)
+{
+	SCB *pCurScb;
+
+	for (;;) {
+
+		tulip_scsi(pCurHcb);	/* Call tulip_scsi              */
+
+		while ((pCurScb = tul_find_done_scb(pCurHcb)) != NULL) {	/* find done entry */
+			if (pCurScb->SCB_TaStat == QUEUE_FULL) {
+				pCurHcb->HCS_MaxTags[pCurScb->SCB_Target] =
+				    pCurHcb->HCS_ActTags[pCurScb->SCB_Target] - 1;
+				pCurScb->SCB_TaStat = 0;
+				tul_append_pend_scb(pCurHcb, pCurScb);
+				continue;
+			}
+			if (!(pCurScb->SCB_Mode & SCM_RSENS)) {		/* not in auto req. sense mode */
+				if (pCurScb->SCB_TaStat == 2) {
+
+					/* clr sync. nego flag */
+
+					if (pCurScb->SCB_Flags & SCF_SENSE) {
+						BYTE len;
+						len = pCurScb->SCB_SenseLen;
+						if (len == 0)
+							len = 1;
+						pCurScb->SCB_BufLen = pCurScb->SCB_SenseLen;
+						pCurScb->SCB_BufPtr = pCurScb->SCB_SensePtr;
+						pCurScb->SCB_Flags &= ~(SCF_SG | SCF_DIR);	/* for xfer_data_in */
+/*                      pCurScb->SCB_Flags |= SCF_NO_DCHK;      */
+						/* so, we won't report worng direction in xfer_data_in,
+						   and won't report HOST_DO_DU in state_6 */
+						pCurScb->SCB_Mode = SCM_RSENS;
+						pCurScb->SCB_Ident &= 0xBF;	/* Disable Disconnect */
+						pCurScb->SCB_TagMsg = 0;
+						pCurScb->SCB_TaStat = 0;
+						pCurScb->SCB_CDBLen = 6;
+						pCurScb->SCB_CDB[0] = SCSICMD_RequestSense;
+						pCurScb->SCB_CDB[1] = 0;
+						pCurScb->SCB_CDB[2] = 0;
+						pCurScb->SCB_CDB[3] = 0;
+						pCurScb->SCB_CDB[4] = len;
+						pCurScb->SCB_CDB[5] = 0;
+						tul_push_pend_scb(pCurHcb, pCurScb);
+						break;
+					}
+				}
+			} else {	/* in request sense mode */
+
+				if (pCurScb->SCB_TaStat == 2) {		/* check contition status again after sending
+									   requset sense cmd 0x3 */
+					pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+				}
+				pCurScb->SCB_TaStat = 2;
+			}
+			pCurScb->SCB_Flags |= SCF_DONE;
+			if (pCurScb->SCB_Flags & SCF_POST) {
+				(*pCurScb->SCB_Post) ((BYTE *) pCurHcb, (BYTE *) pCurScb);
+			}
+		}		/* while */
+
+		/* find_active: */
+		if (TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0) & TSS_INT_PENDING)
+			continue;
+
+		if (pCurHcb->HCS_ActScb) {	/* return to OS and wait for xfer_done_ISR/Selected_ISR */
+			return 1;	/* return to OS, enable interrupt */
+		}
+		/* Check pending SCB            */
+		if (tul_find_first_pend_scb(pCurHcb) == NULL) {
+			return 1;	/* return to OS, enable interrupt */
+		}
+	}			/* End of for loop */
+	/* statement won't reach here */
+}
+
+
+
+
+/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+/***************************************************************************/
+
+/***************************************************************************/
+void tulip_scsi(HCS * pCurHcb)
+{
+	SCB *pCurScb;
+	TCS *pCurTcb;
+
+	/* make sure to service interrupt asap */
+
+	if ((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0)) & TSS_INT_PENDING) {
+
+		pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
+		pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
+		pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+		if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* SCSI bus reset detected      */
+			int_tul_scsi_rst(pCurHcb);
+			return;
+		}
+		if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if selected/reselected interrupt */
+			if (int_tul_resel(pCurHcb) == 0)
+				tul_next_state(pCurHcb);
+			return;
+		}
+		if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {
+			int_tul_busfree(pCurHcb);
+			return;
+		}
+		if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
+			int_tul_busfree(pCurHcb);	/* unexpected bus free or sel timeout */
+			return;
+		}
+		if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {	/* func complete or Bus service */
+			if ((pCurScb = pCurHcb->HCS_ActScb) != NULL)
+				tul_next_state(pCurHcb);
+			return;
+		}
+	}
+	if (pCurHcb->HCS_ActScb != NULL)
+		return;
+
+	if ((pCurScb = tul_find_first_pend_scb(pCurHcb)) == NULL)
+		return;
+
+	/* program HBA's SCSI ID & target SCSI ID */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId,
+	     (pCurHcb->HCS_SCSI_ID << 4) | (pCurScb->SCB_Target & 0x0F));
+	if (pCurScb->SCB_Opcode == ExecSCSI) {
+		pCurTcb = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+
+		if (pCurScb->SCB_TagMsg)
+			pCurTcb->TCS_DrvFlags |= TCF_DRV_EN_TAG;
+		else
+			pCurTcb->TCS_DrvFlags &= ~TCF_DRV_EN_TAG;
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
+		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {	/* do wdtr negotiation          */
+			tul_select_atn_stop(pCurHcb, pCurScb);
+		} else {
+			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync negotiation          */
+				tul_select_atn_stop(pCurHcb, pCurScb);
+			} else {
+				if (pCurScb->SCB_TagMsg)
+					tul_select_atn3(pCurHcb, pCurScb);
+				else
+					tul_select_atn(pCurHcb, pCurScb);
+			}
+		}
+		if (pCurScb->SCB_Flags & SCF_POLL) {
+			while (wait_tulip(pCurHcb) != -1) {
+				if (tul_next_state(pCurHcb) == -1)
+					break;
+			}
+		}
+	} else if (pCurScb->SCB_Opcode == BusDevRst) {
+		tul_select_atn_stop(pCurHcb, pCurScb);
+		pCurScb->SCB_NxtStat = 8;
+		if (pCurScb->SCB_Flags & SCF_POLL) {
+			while (wait_tulip(pCurHcb) != -1) {
+				if (tul_next_state(pCurHcb) == -1)
+					break;
+			}
+		}
+	} else if (pCurScb->SCB_Opcode == AbortCmd) {
+		ULONG srbp;
+
+		srbp = (ULONG) pCurScb->SCB_Srb;
+/* 08/03/98 */
+		if (tul_abort_srb(pCurHcb, srbp) != 0) {
+
+
+			tul_unlink_pend_scb(pCurHcb, pCurScb);
+
+			tul_release_scb(pCurHcb, pCurScb);
+		} else {
+			pCurScb->SCB_Opcode = BusDevRst;
+			tul_select_atn_stop(pCurHcb, pCurScb);
+			pCurScb->SCB_NxtStat = 8;
+		}
+
+/* 08/03/98 */
+	} else {
+		tul_unlink_pend_scb(pCurHcb, pCurScb);
+		pCurScb->SCB_HaStat = 0x16;	/* bad command */
+		tul_append_done_scb(pCurHcb, pCurScb);
+	}
+	return;
+}
+
+
+/***************************************************************************/
+int tul_next_state(HCS * pCurHcb)
+{
+	int next;
+
+	next = pCurHcb->HCS_ActScb->SCB_NxtStat;
+	for (;;) {
+		switch (next) {
+		case 1:
+			next = tul_state_1(pCurHcb);
+			break;
+		case 2:
+			next = tul_state_2(pCurHcb);
+			break;
+		case 3:
+			next = tul_state_3(pCurHcb);
+			break;
+		case 4:
+			next = tul_state_4(pCurHcb);
+			break;
+		case 5:
+			next = tul_state_5(pCurHcb);
+			break;
+		case 6:
+			next = tul_state_6(pCurHcb);
+			break;
+		case 7:
+			next = tul_state_7(pCurHcb);
+			break;
+		case 8:
+			return (tul_bus_device_reset(pCurHcb));
+		default:
+			return (tul_bad_seq(pCurHcb));
+		}
+		if (next <= 0)
+			return next;
+	}
+}
+
+
+/***************************************************************************/
+/* sTate after selection with attention & stop */
+int tul_state_1(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+#if DEBUG_STATE
+	printk("-s1-");
+#endif
+
+	tul_unlink_pend_scb(pCurHcb, pCurScb);
+	tul_append_busy_scb(pCurHcb, pCurScb);
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+	/* ATN on */
+	if (pCurHcb->HCS_Phase == MSG_OUT) {
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, (TSC_EN_BUS_IN | TSC_HW_RESELECT));
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
+
+		if (pCurScb->SCB_TagMsg) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+		}
+		if ((pCurTcb->TCS_Flags & (TCF_WDTR_DONE | TCF_NO_WDTR)) == 0) {
+
+			pCurTcb->TCS_Flags |= TCF_WDTR_DONE;
+
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);	/* Extended msg length */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* Sync request */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* Start from 16 bits */
+		} else if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {
+
+			pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
+
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* extended msg length */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
+		}
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+		if (wait_tulip(pCurHcb) == -1)
+			return (-1);
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
+	return (3);
+}
+
+
+/***************************************************************************/
+/* state after selection with attention */
+/* state after selection with attention3 */
+int tul_state_2(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+#if DEBUG_STATE
+	printk("-s2-");
+#endif
+
+	tul_unlink_pend_scb(pCurHcb, pCurScb);
+	tul_append_busy_scb(pCurHcb, pCurScb);
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+
+	if (pCurHcb->HCS_JSStatus1 & TSS_CMD_PH_CMP) {
+		return (4);
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
+	return (3);
+}
+
+/***************************************************************************/
+/* state before CDB xfer is done */
+int tul_state_3(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	int i;
+
+#if DEBUG_STATE
+	printk("-s3-");
+#endif
+	for (;;) {
+		switch (pCurHcb->HCS_Phase) {
+		case CMD_OUT:	/* Command out phase            */
+			for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+			if (wait_tulip(pCurHcb) == -1)
+				return (-1);
+			if (pCurHcb->HCS_Phase == CMD_OUT) {
+				return (tul_bad_seq(pCurHcb));
+			}
+			return (4);
+
+		case MSG_IN:	/* Message in phase             */
+			pCurScb->SCB_NxtStat = 3;
+			if (tul_msgin(pCurHcb) == -1)
+				return (-1);
+			break;
+
+		case STATUS_IN:	/* Status phase                 */
+			if (tul_status_msg(pCurHcb) == -1)
+				return (-1);
+			break;
+
+		case MSG_OUT:	/* Message out phase            */
+			if (pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) {
+
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+				if (wait_tulip(pCurHcb) == -1)
+					return (-1);
+
+			} else {
+				pCurTcb->TCS_Flags |= TCF_SYNC_DONE;
+
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);	/* ext. msg len */
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);	/* sync request */
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, tul_rate_tbl[pCurTcb->TCS_Flags & TCF_SCSI_RATE]);
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MAX_OFFSET);	/* REQ/ACK offset */
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+				if (wait_tulip(pCurHcb) == -1)
+					return (-1);
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7));
+
+			}
+			break;
+
+		default:
+			return (tul_bad_seq(pCurHcb));
+		}
+	}
+}
+
+
+/***************************************************************************/
+int tul_state_4(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+#if DEBUG_STATE
+	printk("-s4-");
+#endif
+	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_NO_XF) {
+		return (6);	/* Go to state 6                */
+	}
+	for (;;) {
+		if (pCurScb->SCB_BufLen == 0)
+			return (6);	/* Go to state 6                */
+
+		switch (pCurHcb->HCS_Phase) {
+
+		case STATUS_IN:	/* Status phase                 */
+			if ((pCurScb->SCB_Flags & SCF_DIR) != 0) {	/* if direction bit set then report data underrun */
+				pCurScb->SCB_HaStat = HOST_DO_DU;
+			}
+			if ((tul_status_msg(pCurHcb)) == -1)
+				return (-1);
+			break;
+
+		case MSG_IN:	/* Message in phase             */
+			pCurScb->SCB_NxtStat = 0x4;
+			if (tul_msgin(pCurHcb) == -1)
+				return (-1);
+			break;
+
+		case MSG_OUT:	/* Message out phase            */
+			if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
+				pCurScb->SCB_BufLen = 0;
+				pCurScb->SCB_HaStat = HOST_DO_DU;
+				if (tul_msgout_ide(pCurHcb) == -1)
+					return (-1);
+				return (6);	/* Go to state 6                */
+			} else {
+				TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+				if (wait_tulip(pCurHcb) == -1)
+					return (-1);
+			}
+			break;
+
+		case DATA_IN:	/* Data in phase                */
+			return (tul_xfer_data_in(pCurHcb));
+
+		case DATA_OUT:	/* Data out phase               */
+			return (tul_xfer_data_out(pCurHcb));
+
+		default:
+			return (tul_bad_seq(pCurHcb));
+		}
+	}
+}
+
+
+/***************************************************************************/
+/* state after dma xfer done or phase change before xfer done */
+int tul_state_5(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	long cnt, xcnt;		/* cannot use unsigned !! code: if (xcnt < 0) */
+
+#if DEBUG_STATE
+	printk("-s5-");
+#endif
+/*------ get remaining count -------*/
+
+	cnt = TUL_RDLONG(pCurHcb->HCS_Base, TUL_SCnt0) & 0x0FFFFFF;
+
+	if (TUL_RD(pCurHcb->HCS_Base, TUL_XCmd) & 0x20) {
+		/* ----------------------- DATA_IN ----------------------------- */
+		/* check scsi parity error */
+		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
+			pCurScb->SCB_HaStat = HOST_DO_DU;
+		}
+		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* DMA xfer pending, Send STOP  */
+			/* tell Hardware  scsi xfer has been terminated */
+			TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, TUL_RD(pCurHcb->HCS_Base, TUL_XCtrl) | 0x80);
+			/* wait until DMA xfer not pending */
+			while (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND);
+		}
+	} else {
+/*-------- DATA OUT -----------*/
+		if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0) {
+			if (pCurHcb->HCS_ActTcs->TCS_JS_Period & TSC_WIDE_SCSI)
+				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F) << 1;
+			else
+				cnt += (TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F);
+		}
+		if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) {	/* if DMA xfer is pending, abort DMA xfer */
+			TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT);
+			/* wait Abort DMA xfer done */
+			while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0);
+		}
+		if ((cnt == 1) && (pCurHcb->HCS_Phase == DATA_OUT)) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+			if (wait_tulip(pCurHcb) == -1) {
+				return (-1);
+			}
+			cnt = 0;
+		} else {
+			if ((TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1) & TSS_XFER_CMP) == 0)
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+		}
+	}
+
+	if (cnt == 0) {
+		pCurScb->SCB_BufLen = 0;
+		return (6);	/* Go to state 6                */
+	}
+	/* Update active data pointer */
+	xcnt = (long) pCurScb->SCB_BufLen - cnt;	/* xcnt== bytes already xferred */
+	pCurScb->SCB_BufLen = (U32) cnt;	/* cnt == bytes left to be xferred */
+	if (pCurScb->SCB_Flags & SCF_SG) {
+		register SG *sgp;
+		ULONG i;
+
+		sgp = &pCurScb->SCB_SGList[pCurScb->SCB_SGIdx];
+		for (i = pCurScb->SCB_SGIdx; i < pCurScb->SCB_SGMax; sgp++, i++) {
+			xcnt -= (long) sgp->SG_Len;
+			if (xcnt < 0) {		/* this sgp xfer half done */
+				xcnt += (long) sgp->SG_Len;	/* xcnt == bytes xferred in this sgp */
+				sgp->SG_Ptr += (U32) xcnt;	/* new ptr to be xfer */
+				sgp->SG_Len -= (U32) xcnt;	/* new len to be xfer */
+				pCurScb->SCB_BufPtr += ((U32) (i - pCurScb->SCB_SGIdx) << 3);
+				/* new SG table ptr */
+				pCurScb->SCB_SGLen = (BYTE) (pCurScb->SCB_SGMax - i);
+				/* new SG table len */
+				pCurScb->SCB_SGIdx = (WORD) i;
+				/* for next disc and come in this loop */
+				return (4);	/* Go to state 4                */
+			}
+			/* else (xcnt >= 0 , i.e. this sgp already xferred */
+		}		/* for */
+		return (6);	/* Go to state 6                */
+	} else {
+		pCurScb->SCB_BufPtr += (U32) xcnt;
+	}
+	return (4);		/* Go to state 4                */
+}
+
+/***************************************************************************/
+/* state after Data phase */
+int tul_state_6(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+#if DEBUG_STATE
+	printk("-s6-");
+#endif
+	for (;;) {
+		switch (pCurHcb->HCS_Phase) {
+		case STATUS_IN:	/* Status phase                 */
+			if ((tul_status_msg(pCurHcb)) == -1)
+				return (-1);
+			break;
+
+		case MSG_IN:	/* Message in phase             */
+			pCurScb->SCB_NxtStat = 6;
+			if ((tul_msgin(pCurHcb)) == -1)
+				return (-1);
+			break;
+
+		case MSG_OUT:	/* Message out phase            */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);		/* msg nop */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+			if (wait_tulip(pCurHcb) == -1)
+				return (-1);
+			break;
+
+		case DATA_IN:	/* Data in phase                */
+			return (tul_xpad_in(pCurHcb));
+
+		case DATA_OUT:	/* Data out phase               */
+			return (tul_xpad_out(pCurHcb));
+
+		default:
+			return (tul_bad_seq(pCurHcb));
+		}
+	}
+}
+
+/***************************************************************************/
+int tul_state_7(HCS * pCurHcb)
+{
+	int cnt, i;
+
+#if DEBUG_STATE
+	printk("-s7-");
+#endif
+	/* flush SCSI FIFO */
+	cnt = TUL_RD(pCurHcb->HCS_Base, TUL_SFifoCnt) & 0x1F;
+	if (cnt) {
+		for (i = 0; i < cnt; i++)
+			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+	}
+	switch (pCurHcb->HCS_Phase) {
+	case DATA_IN:		/* Data in phase                */
+	case DATA_OUT:		/* Data out phase               */
+		return (tul_bad_seq(pCurHcb));
+	default:
+		return (6);	/* Go to state 6                */
+	}
+}
+
+/***************************************************************************/
+int tul_xfer_data_in(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DOUT) {
+		return (6);	/* wrong direction */
+	}
+	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_IN);	/* 7/25/95 */
+
+	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_IN);
+	} else {
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_IN);
+	}
+	pCurScb->SCB_NxtStat = 0x5;
+	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
+}
+
+
+/***************************************************************************/
+int tul_xfer_data_out(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+	if ((pCurScb->SCB_Flags & SCF_DIR) == SCF_DIN) {
+		return (6);	/* wrong direction */
+	}
+	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, pCurScb->SCB_BufLen);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_DMA_OUT);
+
+	if (pCurScb->SCB_Flags & SCF_SG) {	/* S/G xfer */
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, ((ULONG) pCurScb->SCB_SGLen) << 3);
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_SG_OUT);
+	} else {
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XCntH, pCurScb->SCB_BufLen);
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_XAddH, pCurScb->SCB_BufPtr);
+		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_OUT);
+	}
+
+	pCurScb->SCB_NxtStat = 0x5;
+	return (0);		/* return to OS, wait xfer done , let jas_isr come in */
+}
+
+
+/***************************************************************************/
+int tul_xpad_in(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+
+	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
+		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
+	}
+	for (;;) {
+		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
+			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+		else
+			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+		if ((wait_tulip(pCurHcb)) == -1) {
+			return (-1);
+		}
+		if (pCurHcb->HCS_Phase != DATA_IN) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+			return (6);
+		}
+		TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+	}
+}
+
+int tul_xpad_out(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+
+	if ((pCurScb->SCB_Flags & SCF_DIR) != SCF_NO_DCHK) {
+		pCurScb->SCB_HaStat = HOST_DO_DU;	/* over run             */
+	}
+	for (;;) {
+		if (pCurTcb->TCS_JS_Period & TSC_WIDE_SCSI)
+			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 2);
+		else
+			TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+		if ((wait_tulip(pCurHcb)) == -1) {
+			return (-1);
+		}
+		if (pCurHcb->HCS_Phase != DATA_OUT) {	/* Disable wide CPU to allow read 16 bits */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+			return (6);
+		}
+	}
+}
+
+
+/***************************************************************************/
+int tul_status_msg(HCS * pCurHcb)
+{				/* status & MSG_IN */
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	BYTE msg;
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_CMD_COMP);
+	if ((wait_tulip(pCurHcb)) == -1) {
+		return (-1);
+	}
+	/* get status */
+	pCurScb->SCB_TaStat = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+
+	if (pCurHcb->HCS_Phase == MSG_OUT) {
+		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
+		} else {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_NOP);
+		}
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+		return (wait_tulip(pCurHcb));
+	}
+	if (pCurHcb->HCS_Phase == MSG_IN) {
+		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+		if (pCurHcb->HCS_JSStatus0 & TSS_PAR_ERROR) {	/* Parity error                 */
+			if ((tul_msgin_accept(pCurHcb)) == -1)
+				return (-1);
+			if (pCurHcb->HCS_Phase != MSG_OUT)
+				return (tul_bad_seq(pCurHcb));
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_PARITY);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+			return (wait_tulip(pCurHcb));
+		}
+		if (msg == 0) {	/* Command complete             */
+
+			if ((pCurScb->SCB_TaStat & 0x18) == 0x10) {	/* No link support              */
+				return (tul_bad_seq(pCurHcb));
+			}
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+			return tul_wait_done_disc(pCurHcb);
+
+		}
+		if ((msg == MSG_LINK_COMP) || (msg == MSG_LINK_FLAG)) {
+			if ((pCurScb->SCB_TaStat & 0x18) == 0x10)
+				return (tul_msgin_accept(pCurHcb));
+		}
+	}
+	return (tul_bad_seq(pCurHcb));
+}
+
+
+/***************************************************************************/
+/* scsi bus free */
+int int_tul_busfree(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+
+	if (pCurScb != NULL) {
+		if (pCurScb->SCB_Status & SCB_SELECT) {		/* selection timeout */
+			tul_unlink_pend_scb(pCurHcb, pCurScb);
+			pCurScb->SCB_HaStat = HOST_SEL_TOUT;
+			tul_append_done_scb(pCurHcb, pCurScb);
+		} else {	/* Unexpected bus free          */
+			tul_unlink_busy_scb(pCurHcb, pCurScb);
+			pCurScb->SCB_HaStat = HOST_BUS_FREE;
+			tul_append_done_scb(pCurHcb, pCurScb);
+		}
+		pCurHcb->HCS_ActScb = NULL;
+		pCurHcb->HCS_ActTcs = NULL;
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
+	return (-1);
+}
+
+
+/***************************************************************************/
+/* scsi bus reset */
+int int_tul_scsi_rst(HCS * pCurHcb)
+{
+	SCB *pCurScb;
+	int i;
+
+	/* if DMA xfer is pending, abort DMA xfer */
+	if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & 0x01) {
+		TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO);
+		/* wait Abort DMA xfer done */
+		while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & 0x04) == 0);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+	}
+	/* Abort all active & disconnected scb */
+	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
+		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+		tul_append_done_scb(pCurHcb, pCurScb);
+	}
+	pCurHcb->HCS_ActScb = NULL;
+	pCurHcb->HCS_ActTcs = NULL;
+
+	/* clr sync nego. done flag */
+	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
+		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+	}
+	return (-1);
+}
+
+
+/***************************************************************************/
+/* scsi reselection */
+int int_tul_resel(HCS * pCurHcb)
+{
+	SCB *pCurScb;
+	TCS *pCurTcb;
+	BYTE tag, msg = 0;
+	BYTE tar, lun;
+
+	if ((pCurScb = pCurHcb->HCS_ActScb) != NULL) {
+		if (pCurScb->SCB_Status & SCB_SELECT) {		/* if waiting for selection complete */
+			pCurScb->SCB_Status &= ~SCB_SELECT;
+		}
+		pCurHcb->HCS_ActScb = NULL;
+	}
+	/* --------- get target id---------------------- */
+	tar = TUL_RD(pCurHcb->HCS_Base, TUL_SBusId);
+	/* ------ get LUN from Identify message----------- */
+	lun = TUL_RD(pCurHcb->HCS_Base, TUL_SIdent) & 0x0F;
+	/* 07/22/98 from 0x1F -> 0x0F */
+	pCurTcb = &pCurHcb->HCS_Tcs[tar];
+	pCurHcb->HCS_ActTcs = pCurTcb;
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurTcb->TCS_SConfig0);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurTcb->TCS_JS_Period);
+
+
+	/* ------------- tag queueing ? ------------------- */
+	if (pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG) {
+		if ((tul_msgin_accept(pCurHcb)) == -1)
+			return (-1);
+		if (pCurHcb->HCS_Phase != MSG_IN)
+			goto no_tag;
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+		if ((wait_tulip(pCurHcb)) == -1)
+			return (-1);
+		msg = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag Message    */
+
+		if ((msg < MSG_STAG) || (msg > MSG_OTAG))	/* Is simple Tag      */
+			goto no_tag;
+
+		if ((tul_msgin_accept(pCurHcb)) == -1)
+			return (-1);
+
+		if (pCurHcb->HCS_Phase != MSG_IN)
+			goto no_tag;
+
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+		if ((wait_tulip(pCurHcb)) == -1)
+			return (-1);
+		tag = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* Read Tag ID       */
+		pCurScb = pCurHcb->HCS_Scb + tag;
+		if ((pCurScb->SCB_Target != tar) || (pCurScb->SCB_Lun != lun)) {
+			return tul_msgout_abort_tag(pCurHcb);
+		}
+		if (pCurScb->SCB_Status != SCB_BUSY) {	/* 03/24/95             */
+			return tul_msgout_abort_tag(pCurHcb);
+		}
+		pCurHcb->HCS_ActScb = pCurScb;
+		if ((tul_msgin_accept(pCurHcb)) == -1)
+			return (-1);
+	} else {		/* No tag               */
+	      no_tag:
+		if ((pCurScb = tul_find_busy_scb(pCurHcb, tar | (lun << 8))) == NULL) {
+			return tul_msgout_abort_targ(pCurHcb);
+		}
+		pCurHcb->HCS_ActScb = pCurScb;
+		if (!(pCurTcb->TCS_DrvFlags & TCF_DRV_EN_TAG)) {
+			if ((tul_msgin_accept(pCurHcb)) == -1)
+				return (-1);
+		}
+	}
+	return 0;
+}
+
+
+/***************************************************************************/
+int int_tul_bad_seq(HCS * pCurHcb)
+{				/* target wrong phase           */
+	SCB *pCurScb;
+	int i;
+
+	tul_reset_scsi(pCurHcb, 10);
+
+	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
+		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+		tul_append_done_scb(pCurHcb, pCurScb);
+	}
+	for (i = 0; i < pCurHcb->HCS_MaxTar; i++) {
+		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);;
+	}
+	return (-1);
+}
+
+
+/***************************************************************************/
+int tul_msgout_abort_targ(HCS * pCurHcb)
+{
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+	if (tul_msgin_accept(pCurHcb) == -1)
+		return (-1);
+	if (pCurHcb->HCS_Phase != MSG_OUT)
+		return (tul_bad_seq(pCurHcb));
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+
+	return tul_wait_disc(pCurHcb);
+}
+
+/***************************************************************************/
+int tul_msgout_abort_tag(HCS * pCurHcb)
+{
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+	if (tul_msgin_accept(pCurHcb) == -1)
+		return (-1);
+	if (pCurHcb->HCS_Phase != MSG_OUT)
+		return (tul_bad_seq(pCurHcb));
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_ABORT_TAG);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+
+	return tul_wait_disc(pCurHcb);
+
+}
+
+/***************************************************************************/
+int tul_msgin(HCS * pCurHcb)
+{
+	TCS *pCurTcb;
+
+	for (;;) {
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+		if ((wait_tulip(pCurHcb)) == -1)
+			return (-1);
+
+		switch (TUL_RD(pCurHcb->HCS_Base, TUL_SFifo)) {
+		case MSG_DISC:	/* Disconnect msg */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+
+			return tul_wait_disc(pCurHcb);
+
+		case MSG_SDP:
+		case MSG_RESTORE:
+		case MSG_NOP:
+			tul_msgin_accept(pCurHcb);
+			break;
+
+		case MSG_REJ:	/* Clear ATN first              */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SSignal,
+			       (TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)));
+			pCurTcb = pCurHcb->HCS_ActTcs;
+			if ((pCurTcb->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0) {	/* do sync nego */
+				TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+			}
+			tul_msgin_accept(pCurHcb);
+			break;
+
+		case MSG_EXTEND:	/* extended msg */
+			tul_msgin_extend(pCurHcb);
+			break;
+
+		case MSG_IGNOREWIDE:
+			tul_msgin_accept(pCurHcb);
+			break;
+
+			/* get */
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+			if (wait_tulip(pCurHcb) == -1)
+				return -1;
+
+			TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 0);	/* put pad  */
+			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get IGNORE field */
+			TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);	/* get pad */
+
+			tul_msgin_accept(pCurHcb);
+			break;
+
+		case MSG_COMP:
+			{
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+				TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+				return tul_wait_done_disc(pCurHcb);
+			}
+		default:
+			tul_msgout_reject(pCurHcb);
+			break;
+		}
+		if (pCurHcb->HCS_Phase != MSG_IN)
+			return (pCurHcb->HCS_Phase);
+	}
+	/* statement won't reach here */
+}
+
+
+
+
+/***************************************************************************/
+int tul_msgout_reject(HCS * pCurHcb)
+{
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+
+	if ((tul_msgin_accept(pCurHcb)) == -1)
+		return (-1);
+
+	if (pCurHcb->HCS_Phase == MSG_OUT) {
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_REJ);		/* Msg reject           */
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+		return (wait_tulip(pCurHcb));
+	}
+	return (pCurHcb->HCS_Phase);
+}
+
+
+
+/***************************************************************************/
+int tul_msgout_ide(HCS * pCurHcb)
+{
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_IDE);		/* Initiator Detected Error */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+	return (wait_tulip(pCurHcb));
+}
+
+
+/***************************************************************************/
+int tul_msgin_extend(HCS * pCurHcb)
+{
+	BYTE len, idx;
+
+	if (tul_msgin_accept(pCurHcb) != MSG_IN)
+		return (pCurHcb->HCS_Phase);
+
+	/* Get extended msg length      */
+	TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+	if (wait_tulip(pCurHcb) == -1)
+		return (-1);
+
+	len = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+	pCurHcb->HCS_Msg[0] = len;
+	for (idx = 1; len != 0; len--) {
+
+		if ((tul_msgin_accept(pCurHcb)) != MSG_IN)
+			return (pCurHcb->HCS_Phase);
+		TUL_WRLONG(pCurHcb->HCS_Base + TUL_SCnt0, 1);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_IN);
+		if (wait_tulip(pCurHcb) == -1)
+			return (-1);
+		pCurHcb->HCS_Msg[idx++] = TUL_RD(pCurHcb->HCS_Base, TUL_SFifo);
+	}
+	if (pCurHcb->HCS_Msg[1] == 1) {		/* if it's synchronous data transfer request */
+		if (pCurHcb->HCS_Msg[0] != 3)	/* if length is not right */
+			return (tul_msgout_reject(pCurHcb));
+		if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_SYNC_NEGO) {	/* Set OFFSET=0 to do async, nego back */
+			pCurHcb->HCS_Msg[3] = 0;
+		} else {
+			if ((tul_msgin_sync(pCurHcb) == 0) &&
+			    (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SYNC_DONE)) {
+				tul_sync_done(pCurHcb);
+				return (tul_msgin_accept(pCurHcb));
+			}
+		}
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+		if ((tul_msgin_accept(pCurHcb)) != MSG_OUT)
+			return (pCurHcb->HCS_Phase);
+		/* sync msg out */
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);
+
+		tul_sync_done(pCurHcb);
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 1);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[3]);
+
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+		return (wait_tulip(pCurHcb));
+	}
+	if ((pCurHcb->HCS_Msg[0] != 2) || (pCurHcb->HCS_Msg[1] != 3))
+		return (tul_msgout_reject(pCurHcb));
+	/* if it's WIDE DATA XFER REQ   */
+	if (pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) {
+		pCurHcb->HCS_Msg[2] = 0;
+	} else {
+		if (pCurHcb->HCS_Msg[2] > 2)	/* > 32 bits            */
+			return (tul_msgout_reject(pCurHcb));
+		if (pCurHcb->HCS_Msg[2] == 2) {		/* == 32                */
+			pCurHcb->HCS_Msg[2] = 1;
+		} else {
+			if ((pCurHcb->HCS_ActTcs->TCS_Flags & TCF_NO_WDTR) == 0) {
+				wdtr_done(pCurHcb);
+				if ((pCurHcb->HCS_ActTcs->TCS_Flags & (TCF_SYNC_DONE | TCF_NO_SYNC_NEGO)) == 0)
+					TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+				return (tul_msgin_accept(pCurHcb));
+			}
+		}
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, ((TUL_RD(pCurHcb->HCS_Base, TUL_SSignal) & (TSC_SET_ACK | 7)) | TSC_SET_ATN));
+
+	if (tul_msgin_accept(pCurHcb) != MSG_OUT)
+		return (pCurHcb->HCS_Phase);
+	/* WDTR msg out                 */
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_EXTEND);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 2);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, 3);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurHcb->HCS_Msg[2]);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+	return (wait_tulip(pCurHcb));
+}
+
+/***************************************************************************/
+int tul_msgin_sync(HCS * pCurHcb)
+{
+	char default_period;
+
+	default_period = tul_rate_tbl[pCurHcb->HCS_ActTcs->TCS_Flags & TCF_SCSI_RATE];
+	if (pCurHcb->HCS_Msg[3] > MAX_OFFSET) {
+		pCurHcb->HCS_Msg[3] = MAX_OFFSET;
+		if (pCurHcb->HCS_Msg[2] < default_period) {
+			pCurHcb->HCS_Msg[2] = default_period;
+			return 1;
+		}
+		if (pCurHcb->HCS_Msg[2] >= 59) {	/* Change to async              */
+			pCurHcb->HCS_Msg[3] = 0;
+		}
+		return 1;
+	}
+	/* offset requests asynchronous transfers ? */
+	if (pCurHcb->HCS_Msg[3] == 0) {
+		return 0;
+	}
+	if (pCurHcb->HCS_Msg[2] < default_period) {
+		pCurHcb->HCS_Msg[2] = default_period;
+		return 1;
+	}
+	if (pCurHcb->HCS_Msg[2] >= 59) {
+		pCurHcb->HCS_Msg[3] = 0;
+		return 1;
+	}
+	return 0;
+}
+
+
+/***************************************************************************/
+int wdtr_done(HCS * pCurHcb)
+{
+	pCurHcb->HCS_ActTcs->TCS_Flags &= ~TCF_SYNC_DONE;
+	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_WDTR_DONE;
+
+	pCurHcb->HCS_ActTcs->TCS_JS_Period = 0;
+	if (pCurHcb->HCS_Msg[2]) {	/* if 16 bit */
+		pCurHcb->HCS_ActTcs->TCS_JS_Period |= TSC_WIDE_SCSI;
+	}
+	pCurHcb->HCS_ActTcs->TCS_SConfig0 &= ~TSC_ALT_PERIOD;
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+
+	return 1;
+}
+
+/***************************************************************************/
+int tul_sync_done(HCS * pCurHcb)
+{
+	int i;
+
+	pCurHcb->HCS_ActTcs->TCS_Flags |= TCF_SYNC_DONE;
+
+	if (pCurHcb->HCS_Msg[3]) {
+		pCurHcb->HCS_ActTcs->TCS_JS_Period |= pCurHcb->HCS_Msg[3];
+		for (i = 0; i < 8; i++) {
+			if (tul_rate_tbl[i] >= pCurHcb->HCS_Msg[2])	/* pick the big one */
+				break;
+		}
+		pCurHcb->HCS_ActTcs->TCS_JS_Period |= (i << 4);
+		pCurHcb->HCS_ActTcs->TCS_SConfig0 |= TSC_ALT_PERIOD;
+	}
+	TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_ActTcs->TCS_SConfig0);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, pCurHcb->HCS_ActTcs->TCS_JS_Period);
+
+	return (-1);
+}
+
+
+int tul_post_scsi_rst(HCS * pCurHcb)
+{
+	SCB *pCurScb;
+	TCS *pCurTcb;
+	int i;
+
+	pCurHcb->HCS_ActScb = 0;
+	pCurHcb->HCS_ActTcs = 0;
+	pCurHcb->HCS_Flags = 0;
+
+	while ((pCurScb = tul_pop_busy_scb(pCurHcb)) != NULL) {
+		pCurScb->SCB_HaStat = HOST_BAD_PHAS;
+		tul_append_done_scb(pCurHcb, pCurScb);
+	}
+	/* clear sync done flag         */
+	pCurTcb = &pCurHcb->HCS_Tcs[0];
+	for (i = 0; i < pCurHcb->HCS_MaxTar; pCurTcb++, i++) {
+		pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE);
+		/* Initialize the sync. xfer register values to an asyn xfer */
+		pCurTcb->TCS_JS_Period = 0;
+		pCurTcb->TCS_SConfig0 = pCurHcb->HCS_SConf1;
+		pCurHcb->HCS_ActTags[0] = 0;	/* 07/22/98 */
+		pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY;	/* 07/22/98 */
+	}			/* for */
+
+	return (-1);
+}
+
+/***************************************************************************/
+void tul_select_atn_stop(HCS * pCurHcb, SCB * pCurScb)
+{
+	pCurScb->SCB_Status |= SCB_SELECT;
+	pCurScb->SCB_NxtStat = 0x1;
+	pCurHcb->HCS_ActScb = pCurScb;
+	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SELATNSTOP);
+	return;
+}
+
+
+/***************************************************************************/
+void tul_select_atn(HCS * pCurHcb, SCB * pCurScb)
+{
+	int i;
+
+	pCurScb->SCB_Status |= SCB_SELECT;
+	pCurScb->SCB_NxtStat = 0x2;
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
+	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
+	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+	pCurHcb->HCS_ActScb = pCurScb;
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN);
+	return;
+}
+
+/***************************************************************************/
+void tul_select_atn3(HCS * pCurHcb, SCB * pCurScb)
+{
+	int i;
+
+	pCurScb->SCB_Status |= SCB_SELECT;
+	pCurScb->SCB_NxtStat = 0x2;
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_Ident);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagMsg);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_TagId);
+	for (i = 0; i < (int) pCurScb->SCB_CDBLen; i++)
+		TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, pCurScb->SCB_CDB[i]);
+	pCurHcb->HCS_ActTcs = &pCurHcb->HCS_Tcs[pCurScb->SCB_Target];
+	pCurHcb->HCS_ActScb = pCurScb;
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_SEL_ATN3);
+	return;
+}
+
+/***************************************************************************/
+/* SCSI Bus Device Reset */
+int tul_bus_device_reset(HCS * pCurHcb)
+{
+	SCB *pCurScb = pCurHcb->HCS_ActScb;
+	TCS *pCurTcb = pCurHcb->HCS_ActTcs;
+	SCB *pTmpScb, *pPrevScb;
+	BYTE tar;
+
+	if (pCurHcb->HCS_Phase != MSG_OUT) {
+		return (int_tul_bad_seq(pCurHcb));	/* Unexpected phase             */
+	}
+	tul_unlink_pend_scb(pCurHcb, pCurScb);
+	tul_release_scb(pCurHcb, pCurScb);
+
+
+	tar = pCurScb->SCB_Target;	/* target                       */
+	pCurTcb->TCS_Flags &= ~(TCF_SYNC_DONE | TCF_WDTR_DONE | TCF_BUSY);
+	/* clr sync. nego & WDTR flags  07/22/98 */
+
+	/* abort all SCB with same target */
+	pPrevScb = pTmpScb = pCurHcb->HCS_FirstBusy;	/* Check Busy queue */
+	while (pTmpScb != NULL) {
+
+		if (pTmpScb->SCB_Target == tar) {
+			/* unlink it */
+			if (pTmpScb == pCurHcb->HCS_FirstBusy) {
+				if ((pCurHcb->HCS_FirstBusy = pTmpScb->SCB_NxtScb) == NULL)
+					pCurHcb->HCS_LastBusy = NULL;
+			} else {
+				pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb;
+				if (pTmpScb == pCurHcb->HCS_LastBusy)
+					pCurHcb->HCS_LastBusy = pPrevScb;
+			}
+			pTmpScb->SCB_HaStat = HOST_ABORTED;
+			tul_append_done_scb(pCurHcb, pTmpScb);
+		}
+		/* Previous haven't change      */
+		else {
+			pPrevScb = pTmpScb;
+		}
+		pTmpScb = pTmpScb->SCB_NxtScb;
+	}
+
+	TUL_WR(pCurHcb->HCS_Base + TUL_SFifo, MSG_DEVRST);
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_XF_FIFO_OUT);
+
+	return tul_wait_disc(pCurHcb);
+
+}
+
+/***************************************************************************/
+int tul_msgin_accept(HCS * pCurHcb)
+{
+	TUL_WR(pCurHcb->HCS_Base + TUL_SCmd, TSC_MSG_ACCEPT);
+	return (wait_tulip(pCurHcb));
+}
+
+/***************************************************************************/
+int wait_tulip(HCS * pCurHcb)
+{
+
+	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
+		 & TSS_INT_PENDING));
+
+	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+	pCurHcb->HCS_Phase = pCurHcb->HCS_JSStatus0 & TSS_PH_MASK;
+	pCurHcb->HCS_JSStatus1 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus1);
+
+	if (pCurHcb->HCS_JSInt & TSS_RESEL_INT) {	/* if SCSI bus reset detected   */
+		return (int_tul_resel(pCurHcb));
+	}
+	if (pCurHcb->HCS_JSInt & TSS_SEL_TIMEOUT) {	/* if selected/reselected timeout interrupt */
+		return (int_tul_busfree(pCurHcb));
+	}
+	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
+		return (int_tul_scsi_rst(pCurHcb));
+	}
+	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
+		if (pCurHcb->HCS_Flags & HCF_EXPECT_DONE_DISC) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
+			tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
+			pCurHcb->HCS_ActScb->SCB_HaStat = 0;
+			tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
+			pCurHcb->HCS_ActScb = NULL;
+			pCurHcb->HCS_ActTcs = NULL;
+			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DONE_DISC;
+			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
+			return (-1);
+		}
+		if (pCurHcb->HCS_Flags & HCF_EXPECT_DISC) {
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
+			pCurHcb->HCS_ActScb = NULL;
+			pCurHcb->HCS_ActTcs = NULL;
+			pCurHcb->HCS_Flags &= ~HCF_EXPECT_DISC;
+			TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+			TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
+			return (-1);
+		}
+		return (int_tul_busfree(pCurHcb));
+	}
+	if (pCurHcb->HCS_JSInt & (TSS_FUNC_COMP | TSS_BUS_SERV)) {
+		return (pCurHcb->HCS_Phase);
+	}
+	return (pCurHcb->HCS_Phase);
+}
+/***************************************************************************/
+int tul_wait_disc(HCS * pCurHcb)
+{
+
+	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
+		 & TSS_INT_PENDING));
+
+
+	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+
+	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
+		return (int_tul_scsi_rst(pCurHcb));
+	}
+	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
+		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
+		pCurHcb->HCS_ActScb = NULL;
+		return (-1);
+	}
+	return (tul_bad_seq(pCurHcb));
+}
+
+/***************************************************************************/
+int tul_wait_done_disc(HCS * pCurHcb)
+{
+
+
+	while (!((pCurHcb->HCS_JSStatus0 = TUL_RD(pCurHcb->HCS_Base, TUL_SStatus0))
+		 & TSS_INT_PENDING));
+
+	pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt);
+
+
+	if (pCurHcb->HCS_JSInt & TSS_SCSIRST_INT) {	/* if SCSI bus reset detected   */
+		return (int_tul_scsi_rst(pCurHcb));
+	}
+	if (pCurHcb->HCS_JSInt & TSS_DISC_INT) {	/* BUS disconnection            */
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);		/* Flush SCSI FIFO  */
+		TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, TSC_INITDEFAULT);
+		TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT);	/* Enable HW reselect       */
+		tul_unlink_busy_scb(pCurHcb, pCurHcb->HCS_ActScb);
+
+		tul_append_done_scb(pCurHcb, pCurHcb->HCS_ActScb);
+		pCurHcb->HCS_ActScb = NULL;
+		return (-1);
+	}
+	return (tul_bad_seq(pCurHcb));
+}
+
+/**************************** EOF *********************************/
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/i91uscsi.h linux/drivers/scsi/i91uscsi.h
--- v2.1.131/linux/drivers/scsi/i91uscsi.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/i91uscsi.h	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,857 @@
+/**************************************************************************
+ * Initio 9100 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.
+ *
+ **************************************************************************/
+
+#include <linux/config.h>
+
+#define ULONG   unsigned long
+#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
+
+#define TOTAL_SG_ENTRY		32
+#define MAX_SUPPORTED_ADAPTERS  8
+#define MAX_OFFSET		15
+#define MAX_TARGETS		16
+
+#define INI_VENDOR_ID   0x1101	/* Initio's PCI vendor ID       */
+#define I950_DEVICE_ID	0x9500	/* Initio's inic-950 product ID   */
+#define I940_DEVICE_ID	0x9400	/* Initio's inic-940 product ID   */
+#define I935_DEVICE_ID	0x9401	/* Initio's inic-935 product ID   */
+
+#define	_I91USCSI_H
+
+typedef struct {
+	unsigned short base;
+	unsigned short vec;
+} i91u_config;
+
+/***************************************/
+/*  Tulip Configuration Register Set */
+/***************************************/
+#define TUL_PVID        0x00	/* Vendor ID                    */
+#define TUL_PDID        0x02	/* Device ID                    */
+#define TUL_PCMD        0x04	/* Command                      */
+#define TUL_PSTUS       0x06	/* Status                       */
+#define TUL_PRID        0x08	/* Revision number              */
+#define TUL_PPI         0x09	/* Programming interface        */
+#define TUL_PSC         0x0A	/* Sub Class                    */
+#define TUL_PBC         0x0B	/* Base Class                   */
+#define TUL_PCLS        0x0C	/* Cache line size              */
+#define TUL_PLTR        0x0D	/* Latency timer                */
+#define TUL_PHDT        0x0E	/* Header type                  */
+#define TUL_PBIST       0x0F	/* BIST                         */
+#define TUL_PBAD        0x10	/* Base address                 */
+#define TUL_PBAD1       0x14	/* Base address                 */
+#define TUL_PBAD2       0x18	/* Base address                 */
+#define TUL_PBAD3       0x1C	/* Base address                 */
+#define TUL_PBAD4       0x20	/* Base address                 */
+#define TUL_PBAD5       0x24	/* Base address                 */
+#define TUL_PRSVD       0x28	/* Reserved                     */
+#define TUL_PRSVD1      0x2C	/* Reserved                     */
+#define TUL_PRAD        0x30	/* Expansion ROM base address   */
+#define TUL_PRSVD2      0x34	/* Reserved                     */
+#define TUL_PRSVD3      0x38	/* Reserved                     */
+#define TUL_PINTL       0x3C	/* Interrupt line               */
+#define TUL_PINTP       0x3D	/* Interrupt pin                */
+#define TUL_PIGNT       0x3E	/* MIN_GNT                      */
+#define TUL_PMGNT       0x3F	/* MAX_GNT                      */
+
+/************************/
+/*  Jasmin Register Set */
+/************************/
+#define TUL_HACFG0      0x40	/* H/A Configuration Register 0         */
+#define TUL_HACFG1      0x41	/* H/A Configuration Register 1         */
+#define TUL_HACFG2      0x42	/* H/A Configuration Register 2         */
+
+#define TUL_SDCFG0      0x44	/* SCSI Device Configuration 0          */
+#define TUL_SDCFG1      0x45	/* SCSI Device Configuration 1          */
+#define TUL_SDCFG2      0x46	/* SCSI Device Configuration 2          */
+#define TUL_SDCFG3      0x47	/* SCSI Device Configuration 3          */
+
+#define TUL_GINTS       0x50	/* Global Interrupt Status Register     */
+#define TUL_GIMSK       0x52	/* Global Interrupt MASK Register       */
+#define TUL_GCTRL       0x54	/* Global Control Register              */
+#define TUL_GCTRL_EEPROM_BIT    0x04
+#define TUL_GCTRL1      0x55	/* Global Control Register              */
+#define TUL_DMACFG      0x5B	/* DMA configuration                    */
+#define TUL_NVRAM       0x5D	/* Non-volatile RAM port                */
+
+#define TUL_SCnt0       0x80	/* 00 R/W Transfer Counter Low          */
+#define TUL_SCnt1       0x81	/* 01 R/W Transfer Counter Mid          */
+#define TUL_SCnt2       0x82	/* 02 R/W Transfer Count High           */
+#define TUL_SFifoCnt    0x83	/* 03 R   FIFO counter                  */
+#define TUL_SIntEnable  0x84	/* 03 W   Interrupt enble               */
+#define TUL_SInt        0x84	/* 04 R   Interrupt Register            */
+#define TUL_SCtrl0      0x85	/* 05 W   Control 0                     */
+#define TUL_SStatus0    0x85	/* 05 R   Status 0                      */
+#define TUL_SCtrl1      0x86	/* 06 W   Control 1                     */
+#define TUL_SStatus1    0x86	/* 06 R   Status 1                      */
+#define TUL_SConfig     0x87	/* 07 W   Configuration                 */
+#define TUL_SStatus2    0x87	/* 07 R   Status 2                      */
+#define TUL_SPeriod     0x88	/* 08 W   Sync. Transfer Period & Offset */
+#define TUL_SOffset     0x88	/* 08 R   Offset                        */
+#define TUL_SScsiId     0x89	/* 09 W   SCSI ID                       */
+#define TUL_SBusId      0x89	/* 09 R   SCSI BUS ID                   */
+#define TUL_STimeOut    0x8A	/* 0A W   Sel/Resel Time Out Register   */
+#define TUL_SIdent      0x8A	/* 0A R   Identify Message Register     */
+#define TUL_SAvail      0x8A	/* 0A R   Availiable Counter Register   */
+#define TUL_SData       0x8B	/* 0B R/W SCSI data in/out              */
+#define TUL_SFifo       0x8C	/* 0C R/W FIFO                          */
+#define TUL_SSignal     0x90	/* 10 R/W SCSI signal in/out            */
+#define TUL_SCmd        0x91	/* 11 R/W Command                       */
+#define TUL_STest0      0x92	/* 12 R/W Test0                         */
+#define TUL_STest1      0x93	/* 13 R/W Test1                         */
+#define TUL_SCFG1	0x94	/* 14 R/W Configuration                 */
+
+#define TUL_XAddH       0xC0	/*DMA Transfer Physical Address         */
+#define TUL_XAddW       0xC8	/*DMA Current Transfer Physical Address */
+#define TUL_XCntH       0xD0	/*DMA Transfer Counter                  */
+#define TUL_XCntW       0xD4	/*DMA Current Transfer Counter          */
+#define TUL_XCmd        0xD8	/*DMA Command Register                  */
+#define TUL_Int         0xDC	/*Interrupt Register                    */
+#define TUL_XStatus     0xDD	/*DMA status Register                   */
+#define TUL_Mask        0xE0	/*Interrupt Mask Register               */
+#define TUL_XCtrl       0xE4	/*DMA Control Register                  */
+#define TUL_XCtrl1      0xE5	/*DMA Control Register 1                */
+#define TUL_XFifo       0xE8	/*DMA FIFO                              */
+
+#define TUL_WCtrl       0xF7	/*Bus master wait state control         */
+#define TUL_DCtrl       0xFB	/*DMA delay control                     */
+
+/*----------------------------------------------------------------------*/
+/*   bit definition for Command register of Configuration Space Header  */
+/*----------------------------------------------------------------------*/
+#define BUSMS           0x04	/* BUS MASTER Enable                    */
+#define IOSPA           0x01	/* IO Space Enable                      */
+
+/*----------------------------------------------------------------------*/
+/* Command Codes of Tulip SCSI Command register                         */
+/*----------------------------------------------------------------------*/
+#define TSC_EN_RESEL    0x80	/* Enable Reselection                   */
+#define TSC_CMD_COMP    0x84	/* Command Complete Sequence            */
+#define TSC_SEL         0x01	/* Select Without ATN Sequence          */
+#define TSC_SEL_ATN     0x11	/* Select With ATN Sequence             */
+#define TSC_SEL_ATN_DMA 0x51	/* Select With ATN Sequence with DMA    */
+#define TSC_SEL_ATN3    0x31	/* Select With ATN3 Sequence            */
+#define TSC_SEL_ATNSTOP 0x12	/* Select With ATN and Stop Sequence    */
+#define TSC_SELATNSTOP  0x1E	/* Select With ATN and Stop Sequence    */
+
+#define TSC_SEL_ATN_DIRECT_IN   0x95	/* Select With ATN Sequence     */
+#define TSC_SEL_ATN_DIRECT_OUT  0x15	/* Select With ATN Sequence     */
+#define TSC_SEL_ATN3_DIRECT_IN  0xB5	/* Select With ATN3 Sequence    */
+#define TSC_SEL_ATN3_DIRECT_OUT 0x35	/* Select With ATN3 Sequence    */
+#define TSC_XF_DMA_OUT_DIRECT   0x06	/* DMA Xfer Infomation out      */
+#define TSC_XF_DMA_IN_DIRECT    0x86	/* DMA Xfer Infomation in       */
+
+#define TSC_XF_DMA_OUT  0x43	/* DMA Xfer Infomation out              */
+#define TSC_XF_DMA_IN   0xC3	/* DMA Xfer Infomation in               */
+#define TSC_XF_FIFO_OUT 0x03	/* FIFO Xfer Infomation out             */
+#define TSC_XF_FIFO_IN  0x83	/* FIFO Xfer Infomation in              */
+
+#define TSC_MSG_ACCEPT  0x0F	/* Message Accept                       */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Control 0 Register                     */
+/*----------------------------------------------------------------------*/
+#define TSC_RST_SEQ     0x20	/* Reset sequence counter               */
+#define TSC_FLUSH_FIFO  0x10	/* Flush FIFO                           */
+#define TSC_ABT_CMD     0x04	/* Abort command (sequence)             */
+#define TSC_RST_CHIP    0x02	/* Reset SCSI Chip                      */
+#define TSC_RST_BUS     0x01	/* Reset SCSI Bus                       */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Control 1 Register                     */
+/*----------------------------------------------------------------------*/
+#define TSC_EN_SCAM     0x80	/* Enable SCAM                          */
+#define TSC_TIMER       0x40	/* Select timeout unit                  */
+#define TSC_EN_SCSI2    0x20	/* SCSI-2 mode                          */
+#define TSC_PWDN        0x10	/* Power down mode                      */
+#define TSC_WIDE_CPU    0x08	/* Wide CPU                             */
+#define TSC_HW_RESELECT 0x04	/* Enable HW reselect                   */
+#define TSC_EN_BUS_OUT  0x02	/* Enable SCSI data bus out latch       */
+#define TSC_EN_BUS_IN   0x01	/* Enable SCSI data bus in latch        */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Configuration Register                 */
+/*----------------------------------------------------------------------*/
+#define TSC_EN_LATCH    0x80	/* Enable phase latch                   */
+#define TSC_INITIATOR   0x40	/* Initiator mode                       */
+#define TSC_EN_SCSI_PAR 0x20	/* Enable SCSI parity                   */
+#define TSC_DMA_8BIT    0x10	/* Alternate dma 8-bits mode            */
+#define TSC_DMA_16BIT   0x08	/* Alternate dma 16-bits mode           */
+#define TSC_EN_WDACK    0x04	/* Enable DACK while wide SCSI xfer     */
+#define TSC_ALT_PERIOD  0x02	/* Alternate sync period mode           */
+#define TSC_DIS_SCSIRST 0x01	/* Disable SCSI bus reset us            */
+
+#define TSC_INITDEFAULT (TSC_INITIATOR | TSC_EN_LATCH | TSC_ALT_PERIOD | TSC_DIS_SCSIRST)
+
+#define TSC_WIDE_SCSI   0x80	/* Enable Wide SCSI                     */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI signal Register                        */
+/*----------------------------------------------------------------------*/
+#define TSC_RST_ACK     0x00	/* Release ACK signal                   */
+#define TSC_RST_ATN     0x00	/* Release ATN signal                   */
+#define TSC_RST_BSY     0x00	/* Release BSY signal                   */
+
+#define TSC_SET_ACK     0x40	/* ACK signal                           */
+#define TSC_SET_ATN     0x08	/* ATN signal                           */
+
+#define TSC_REQI        0x80	/* REQ signal                           */
+#define TSC_ACKI        0x40	/* ACK signal                           */
+#define TSC_BSYI        0x20	/* BSY signal                           */
+#define TSC_SELI        0x10	/* SEL signal                           */
+#define TSC_ATNI        0x08	/* ATN signal                           */
+#define TSC_MSGI        0x04	/* MSG signal                           */
+#define TSC_CDI         0x02	/* C/D signal                           */
+#define TSC_IOI         0x01	/* I/O signal                           */
+
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Status 0 Register                      */
+/*----------------------------------------------------------------------*/
+#define TSS_INT_PENDING 0x80	/* Interrupt pending            */
+#define TSS_SEQ_ACTIVE  0x40	/* Sequencer active             */
+#define TSS_XFER_CNT    0x20	/* Transfer counter zero        */
+#define TSS_FIFO_EMPTY  0x10	/* FIFO empty                   */
+#define TSS_PAR_ERROR   0x08	/* SCSI parity error            */
+#define TSS_PH_MASK     0x07	/* SCSI phase mask              */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Status 1 Register                      */
+/*----------------------------------------------------------------------*/
+#define TSS_STATUS_RCV  0x08	/* Status received              */
+#define TSS_MSG_SEND    0x40	/* Message sent                 */
+#define TSS_CMD_PH_CMP  0x20	/* command phase done              */
+#define TSS_DATA_PH_CMP 0x10	/* Data phase done              */
+#define TSS_STATUS_SEND 0x08	/* Status sent                  */
+#define TSS_XFER_CMP    0x04	/* Transfer completed           */
+#define TSS_SEL_CMP     0x02	/* Selection completed          */
+#define TSS_ARB_CMP     0x01	/* Arbitration completed        */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Status 2 Register                      */
+/*----------------------------------------------------------------------*/
+#define TSS_CMD_ABTED   0x80	/* Command aborted              */
+#define TSS_OFFSET_0    0x40	/* Offset counter zero          */
+#define TSS_FIFO_FULL   0x20	/* FIFO full                    */
+#define TSS_TIMEOUT_0   0x10	/* Timeout counter zero         */
+#define TSS_BUSY_RLS    0x08	/* Busy release                 */
+#define TSS_PH_MISMATCH 0x04	/* Phase mismatch               */
+#define TSS_SCSI_BUS_EN 0x02	/* SCSI data bus enable         */
+#define TSS_SCSIRST     0x01	/* SCSI bus reset in progress   */
+
+/*----------------------------------------------------------------------*/
+/* bit definition for Tulip SCSI Interrupt Register                     */
+/*----------------------------------------------------------------------*/
+#define TSS_RESEL_INT   0x80	/* Reselected interrupt         */
+#define TSS_SEL_TIMEOUT 0x40	/* Selected/reselected timeout  */
+#define TSS_BUS_SERV    0x20
+#define TSS_SCSIRST_INT 0x10	/* SCSI bus reset detected      */
+#define TSS_DISC_INT    0x08	/* Disconnected interrupt       */
+#define TSS_SEL_INT     0x04	/* Select interrupt             */
+#define TSS_SCAM_SEL    0x02	/* SCAM selected                */
+#define TSS_FUNC_COMP   0x01
+
+/*----------------------------------------------------------------------*/
+/* SCSI Phase Codes.                                                    */
+/*----------------------------------------------------------------------*/
+#define DATA_OUT        0
+#define DATA_IN         1	/* 4                            */
+#define CMD_OUT         2
+#define STATUS_IN       3	/* 6                            */
+#define MSG_OUT         6	/* 3                            */
+#define MSG_IN          7
+
+
+
+/*----------------------------------------------------------------------*/
+/* Command Codes of Tulip xfer Command register                         */
+/*----------------------------------------------------------------------*/
+#define TAX_X_FORC      0x02
+#define TAX_X_ABT       0x04
+#define TAX_X_CLR_FIFO  0x08
+
+#define TAX_X_IN        0x21
+#define TAX_X_OUT       0x01
+#define TAX_SG_IN       0xA1
+#define TAX_SG_OUT      0x81
+
+/*----------------------------------------------------------------------*/
+/* Tulip Interrupt Register                                             */
+/*----------------------------------------------------------------------*/
+#define XCMP            0x01
+#define FCMP            0x02
+#define XABT            0x04
+#define XERR            0x08
+#define SCMP            0x10
+#define IPEND           0x80
+
+/*----------------------------------------------------------------------*/
+/* Tulip DMA Status Register                                            */
+/*----------------------------------------------------------------------*/
+#define XPEND           0x01	/* Transfer pending             */
+#define FEMPTY          0x02	/* FIFO empty                   */
+
+
+
+/*----------------------------------------------------------------------*/
+/* bit definition for TUL_GCTRL                                         */
+/*----------------------------------------------------------------------*/
+#define EXTSG           0x80
+#define EXTAD           0x60
+#define SEG4K           0x08
+#define EEPRG           0x04
+#define MRMUL           0x02
+
+/*----------------------------------------------------------------------*/
+/* bit definition for TUL_NVRAM                                         */
+/*----------------------------------------------------------------------*/
+#define SE2CS           0x08
+#define SE2CLK          0x04
+#define SE2DO           0x02
+#define SE2DI           0x01
+
+
+/************************************************************************/
+/*              Scatter-Gather Element Structure                        */
+/************************************************************************/
+typedef struct SG_Struc {
+	U32 SG_Ptr;		/* Data Pointer */
+	U32 SG_Len;		/* Data Length */
+} SG;
+
+/***********************************************************************
+		SCSI Control Block
+************************************************************************/
+typedef struct Scsi_Ctrl_Blk {
+	struct Scsi_Ctrl_Blk *SCB_NxtScb;
+	UBYTE SCB_Status;	/*4 */
+	UBYTE SCB_NxtStat;	/*5 */
+	UBYTE SCB_Mode;		/*6 */
+	UBYTE SCB_Msgin;	/*7 SCB_Res0 */
+	UWORD SCB_SGIdx;	/*8 */
+	UWORD SCB_SGMax;	/*A */
+#ifdef ALPHA
+	U32 SCB_Reserved[2];	/*C */
+#else
+	U32 SCB_Reserved[3];	/*C */
+#endif
+
+	U32 SCB_XferLen;	/*18 Current xfer len           */
+	U32 SCB_TotXLen;	/*1C Total xfer len             */
+	U32 SCB_PAddr;		/*20 SCB phy. Addr. */
+
+	UBYTE SCB_Opcode;	/*24 SCB command code */
+	UBYTE SCB_Flags;	/*25 SCB Flags */
+	UBYTE SCB_Target;	/*26 Target Id */
+	UBYTE SCB_Lun;		/*27 Lun */
+	U32 SCB_BufPtr;		/*28 Data Buffer Pointer */
+	U32 SCB_BufLen;		/*2C Data Allocation Length */
+	UBYTE SCB_SGLen;	/*30 SG list # */
+	UBYTE SCB_SenseLen;	/*31 Sense Allocation Length */
+	UBYTE SCB_HaStat;	/*32 */
+	UBYTE SCB_TaStat;	/*33 */
+	UBYTE SCB_CDBLen;	/*34 CDB Length */
+	UBYTE SCB_Ident;	/*35 Identify */
+	UBYTE SCB_TagMsg;	/*36 Tag Message */
+	UBYTE SCB_TagId;	/*37 Queue Tag */
+	UBYTE SCB_CDB[12];	/*38 */
+	U32 SCB_SGPAddr;	/*44 SG List/Sense Buf phy. Addr. */
+	U32 SCB_SensePtr;	/*48 Sense data pointer */
+	void (*SCB_Post) (BYTE *, BYTE *);	/*4C POST routine */
+	unsigned char *SCB_Srb;	/*50 SRB Pointer */
+	SG SCB_SGList[TOTAL_SG_ENTRY];	/*54 Start of SG list */
+} SCB;
+
+/* Bit Definition for SCB_Status */
+#define SCB_RENT        0x01
+#define SCB_PEND        0x02
+#define SCB_CONTIG      0x04	/* Contigent Allegiance */
+#define SCB_SELECT      0x08
+#define SCB_BUSY        0x10
+#define SCB_DONE        0x20
+
+
+/* Opcodes of SCB_Opcode */
+#define ExecSCSI        0x1
+#define BusDevRst       0x2
+#define AbortCmd        0x3
+
+
+/* Bit Definition for SCB_Mode */
+#define SCM_RSENS       0x01	/* request sense mode */
+
+
+/* Bit Definition for SCB_Flags */
+#define SCF_DONE        0x01
+#define SCF_POST        0x02
+#define SCF_SENSE       0x04
+#define SCF_DIR         0x18
+#define SCF_NO_DCHK     0x00
+#define SCF_DIN         0x08
+#define SCF_DOUT        0x10
+#define SCF_NO_XF       0x18
+#define SCF_WR_VF       0x20	/* Write verify turn on         */
+#define SCF_POLL        0x40
+#define SCF_SG          0x80
+
+/* Error Codes for SCB_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_ABORTED    0x1A	/* 07/21/98 */
+#define HOST_SCSI_RST   0x1B
+#define HOST_DEV_RST    0x1C
+
+/* Error Codes for SCB_TaStat */
+#define TARGET_CHKCOND  0x02
+#define TARGET_BUSY     0x08
+#define QUEUE_FULL	0x28
+
+/* SCSI MESSAGE */
+#define MSG_COMP        0x00
+#define MSG_EXTEND      0x01
+#define MSG_SDP         0x02
+#define MSG_RESTORE     0x03
+#define MSG_DISC        0x04
+#define MSG_IDE         0x05
+#define MSG_ABORT       0x06
+#define MSG_REJ         0x07
+#define MSG_NOP         0x08
+#define MSG_PARITY      0x09
+#define MSG_LINK_COMP   0x0A
+#define MSG_LINK_FLAG   0x0B
+#define MSG_DEVRST      0x0C
+#define MSG_ABORT_TAG   0x0D
+
+/* 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
+
+/***********************************************************************
+		Target Device Control Structure
+**********************************************************************/
+
+typedef struct Tar_Ctrl_Struc {
+	UWORD TCS_Flags;	/* 0 */
+	UBYTE TCS_JS_Period;	/* 2 */
+	UBYTE TCS_SConfig0;	/* 3 */
+
+	UWORD TCS_DrvFlags;	/* 4 */
+	UBYTE TCS_DrvHead;	/* 6 */
+	UBYTE TCS_DrvSector;	/* 7 */
+} TCS;
+
+/***********************************************************************
+		Target Device Control Structure
+**********************************************************************/
+
+/* Bit Definition for TCF_Flags */
+#define TCF_SCSI_RATE           0x0007
+#define TCF_EN_DISC             0x0008
+#define TCF_NO_SYNC_NEGO        0x0010
+#define TCF_NO_WDTR             0x0020
+#define TCF_EN_255              0x0040
+#define TCF_EN_START            0x0080
+#define TCF_WDTR_DONE           0x0100
+#define TCF_SYNC_DONE           0x0200
+#define TCF_BUSY                0x0400
+
+
+/* Bit Definition for TCF_DrvFlags */
+#define TCF_DRV_BUSY            0x01	/* Indicate target busy(driver) */
+#define TCF_DRV_EN_TAG          0x0800
+#define TCF_DRV_255_63          0x0400
+
+typedef struct I91u_Adpt_Struc {
+	UWORD ADPT_BIOS;	/* 0 */
+	UWORD ADPT_BASE;	/* 1 */
+	UBYTE ADPT_Bus;		/* 2 */
+	UBYTE ADPT_Device;	/* 3 */
+	UBYTE ADPT_INTR;	/* 4 */
+} INI_ADPT_STRUCT;
+
+
+/***********************************************************************
+	      Host Adapter Control Structure
+************************************************************************/
+typedef struct Ha_Ctrl_Struc {
+	UWORD HCS_Base;		/* 00 */
+	UWORD HCS_BIOS;		/* 02 */
+	UBYTE HCS_Intr;		/* 04 */
+	UBYTE HCS_SCSI_ID;	/* 05 */
+	UBYTE HCS_MaxTar;	/* 06 */
+	UBYTE HCS_NumScbs;	/* 07 */
+
+	UBYTE HCS_Flags;	/* 08 */
+	UBYTE HCS_Index;	/* 09 */
+	UBYTE HCS_HaId;		/* 0A */
+	UBYTE HCS_Config;	/* 0B */
+	UWORD HCS_IdMask;	/* 0C */
+	UBYTE HCS_Semaph;	/* 0E */
+	UBYTE HCS_Phase;	/* 0F */
+	UBYTE HCS_JSStatus0;	/* 10 */
+	UBYTE HCS_JSInt;	/* 11 */
+	UBYTE HCS_JSStatus1;	/* 12 */
+	UBYTE HCS_SConf1;	/* 13 */
+
+	UBYTE HCS_Msg[8];	/* 14 */
+	SCB *HCS_NxtAvail;	/* 1C */
+	SCB *HCS_Scb;		/* 20 */
+	SCB *HCS_ScbEnd;	/* 24 */
+	SCB *HCS_NxtPend;	/* 28 */
+	SCB *HCS_NxtContig;	/* 2C */
+	SCB *HCS_ActScb;	/* 30 */
+	TCS *HCS_ActTcs;	/* 34 */
+
+	SCB *HCS_FirstAvail;	/* 38 */
+	SCB *HCS_LastAvail;	/* 3C */
+	SCB *HCS_FirstPend;	/* 40 */
+	SCB *HCS_LastPend;	/* 44 */
+	SCB *HCS_FirstBusy;	/* 48 */
+	SCB *HCS_LastBusy;	/* 4C */
+	SCB *HCS_FirstDone;	/* 50 */
+	SCB *HCS_LastDone;	/* 54 */
+	UBYTE HCS_MaxTags[16];	/* 58 */
+	UBYTE HCS_ActTags[16];	/* 68 */
+	TCS HCS_Tcs[MAX_TARGETS];	/* 78 */
+	ULONG pSRB_head;	/* SRB save queue header     */
+	ULONG pSRB_tail;	/* SRB save queue tail       */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spinlock_t HCS_AvailLock;
+	spinlock_t HCS_SemaphLock;
+	spinlock_t pSRB_lock;	/* SRB queue lock            */
+#endif
+} HCS;
+
+/* Bit Definition for HCB_Config */
+#define HCC_SCSI_RESET          0x01
+#define HCC_EN_PAR              0x02
+#define HCC_ACT_TERM1           0x04
+#define HCC_ACT_TERM2           0x08
+#define HCC_AUTO_TERM           0x10
+#define HCC_EN_PWR              0x80
+
+/* Bit Definition for HCB_Flags */
+#define HCF_EXPECT_DISC         0x01
+#define HCF_EXPECT_SELECT       0x02
+#define HCF_EXPECT_RESET        0x10
+#define HCF_EXPECT_DONE_DISC    0x20
+
+/******************************************************************
+	Serial EEProm
+*******************************************************************/
+
+typedef struct _NVRAM_SCSI {	/* SCSI channel configuration   */
+	UCHAR NVM_ChSCSIID;	/* 0Ch -> Channel SCSI ID       */
+	UCHAR NVM_ChConfig1;	/* 0Dh -> Channel config 1      */
+	UCHAR NVM_ChConfig2;	/* 0Eh -> Channel config 2      */
+	UCHAR NVM_NumOfTarg;	/* 0Fh -> Number of SCSI target */
+	/* SCSI target configuration    */
+	UCHAR NVM_Targ0Config;	/* 10h -> Target 0 configuration */
+	UCHAR NVM_Targ1Config;	/* 11h -> Target 1 configuration */
+	UCHAR NVM_Targ2Config;	/* 12h -> Target 2 configuration */
+	UCHAR NVM_Targ3Config;	/* 13h -> Target 3 configuration */
+	UCHAR NVM_Targ4Config;	/* 14h -> Target 4 configuration */
+	UCHAR NVM_Targ5Config;	/* 15h -> Target 5 configuration */
+	UCHAR NVM_Targ6Config;	/* 16h -> Target 6 configuration */
+	UCHAR NVM_Targ7Config;	/* 17h -> Target 7 configuration */
+	UCHAR NVM_Targ8Config;	/* 18h -> Target 8 configuration */
+	UCHAR NVM_Targ9Config;	/* 19h -> Target 9 configuration */
+	UCHAR NVM_TargAConfig;	/* 1Ah -> Target A configuration */
+	UCHAR NVM_TargBConfig;	/* 1Bh -> Target B configuration */
+	UCHAR NVM_TargCConfig;	/* 1Ch -> Target C configuration */
+	UCHAR NVM_TargDConfig;	/* 1Dh -> Target D configuration */
+	UCHAR NVM_TargEConfig;	/* 1Eh -> Target E configuration */
+	UCHAR NVM_TargFConfig;	/* 1Fh -> Target F configuration */
+} NVRAM_SCSI;
+
+typedef struct _NVRAM {
+/*----------header ---------------*/
+	USHORT NVM_Signature;	/* 0,1: Signature */
+	UCHAR NVM_Size;		/* 2:   Size of data structure */
+	UCHAR NVM_Revision;	/* 3:   Revision of data structure */
+	/* ----Host Adapter Structure ---- */
+	UCHAR NVM_ModelByte0;	/* 4:   Model number (byte 0) */
+	UCHAR NVM_ModelByte1;	/* 5:   Model number (byte 1) */
+	UCHAR NVM_ModelInfo;	/* 6:   Model information         */
+	UCHAR NVM_NumOfCh;	/* 7:   Number of SCSI channel */
+	UCHAR NVM_BIOSConfig1;	/* 8:   BIOS configuration 1  */
+	UCHAR NVM_BIOSConfig2;	/* 9:   BIOS configuration 2  */
+	UCHAR NVM_HAConfig1;	/* A:   Hoat adapter configuration 1 */
+	UCHAR NVM_HAConfig2;	/* B:   Hoat adapter configuration 2 */
+	NVRAM_SCSI NVM_SCSIInfo[2];
+	UCHAR NVM_reserved[10];
+	/* ---------- CheckSum ----------       */
+	USHORT NVM_CheckSum;	/* 0x3E, 0x3F: Checksum of NVRam        */
+} NVRAM, *PNVRAM;
+
+/* Bios Configuration for nvram->BIOSConfig1                            */
+#define NBC1_ENABLE             0x01	/* BIOS enable                  */
+#define NBC1_8DRIVE             0x02	/* Support more than 2 drives   */
+#define NBC1_REMOVABLE          0x04	/* Support removable drive      */
+#define NBC1_INT19              0x08	/* Intercept int 19h            */
+#define NBC1_BIOSSCAN           0x10	/* Dynamic BIOS scan            */
+#define NBC1_LUNSUPPORT         0x40	/* Support LUN                  */
+
+/* HA Configuration Byte 1                                              */
+#define NHC1_BOOTIDMASK 0x0F	/* Boot ID number               */
+#define NHC1_LUNMASK    0x70	/* Boot LUN number              */
+#define NHC1_CHANMASK   0x80	/* Boot Channel number          */
+
+/* Bit definition for nvram->SCSIconfig1                                */
+#define NCC1_BUSRESET           0x01	/* Reset SCSI bus at power up   */
+#define NCC1_PARITYCHK          0x02	/* SCSI parity enable           */
+#define NCC1_ACTTERM1           0x04	/* Enable active terminator 1   */
+#define NCC1_ACTTERM2           0x08	/* Enable active terminator 2   */
+#define NCC1_AUTOTERM           0x10	/* Enable auto terminator       */
+#define NCC1_PWRMGR             0x80	/* Enable power management      */
+
+/* Bit definition for SCSI Target configuration byte                    */
+#define NTC_DISCONNECT          0x08	/* Enable SCSI disconnect       */
+#define NTC_SYNC                0x10	/* SYNC_NEGO                    */
+#define NTC_NO_WDTR             0x20	/* SYNC_NEGO                    */
+#define NTC_1GIGA               0x40	/* 255 head / 63 sectors (64/32) */
+#define NTC_SPINUP              0x80	/* Start disk drive             */
+
+/*      Default NVRam values                                            */
+#define INI_SIGNATURE           0xC925
+#define NBC1_DEFAULT            (NBC1_ENABLE)
+#define NCC1_DEFAULT            (NCC1_BUSRESET | NCC1_AUTOTERM | NCC1_PARITYCHK)
+#define NTC_DEFAULT             (NTC_NO_WDTR | NTC_1GIGA | NTC_DISCONNECT)
+
+/* SCSI related definition                                              */
+#define DISC_NOT_ALLOW          0x80	/* Disconnect is not allowed    */
+#define DISC_ALLOW              0xC0	/* Disconnect is allowed        */
+#define SCSICMD_RequestSense    0x03
+
+
+/*----------------------------------------------------------------------*/
+/*                              PCI                                     */
+/*----------------------------------------------------------------------*/
+#define PCI_FUNCTION_ID         0xB1
+#define PCI_BIOS_PRESENT        0x01
+#define FIND_PCI_DEVICE         0x02
+#define FIND_PCI_CLASS_CODE     0x03
+#define GENERATE_SPECIAL_CYCLE  0x06
+#define READ_CONFIG_BYTE        0x08
+#define READ_CONFIG_WORD        0x09
+#define READ_CONFIG_DWORD       0x0A
+#define WRITE_CONFIG_BYTE       0x0B
+#define WRITE_CONFIG_WORD       0x0C
+#define WRITE_CONFIG_DWORD      0x0D
+
+#define SUCCESSFUL              0x00
+#define FUNC_NOT_SUPPORTED      0x81
+#define BAD_VENDOR_ID           0x83	/* Bad vendor ID                */
+#define DEVICE_NOT_FOUND        0x86	/* PCI device not found         */
+#define BAD_REGISTER_NUMBER     0x87
+
+#define MAX_PCI_DEVICES         21	/* Maximum devices supportted   */
+
+#define MAX_PCI_CHANL           4
+
+typedef struct _BIOS32_ENTRY_STRUCTURE {
+	DWORD Signatures;	/* Should be "_32_"             */
+	DWORD BIOS32Entry;	/* 32-bit physical address      */
+	BYTE Revision;		/* Revision level, should be 0  */
+	BYTE Length;		/* Multiply of 16, should be 1  */
+	BYTE CheckSum;		/* Checksum of whole structure  */
+	BYTE Reserved[5];	/* Reserved                     */
+} BIOS32_ENTRY_STRUCTURE, *PBIOS32_ENTRY_STRUCTURE;
+
+typedef struct {
+	union {
+		unsigned int eax;
+		struct {
+			unsigned short ax;
+		} word;
+		struct {
+			unsigned char al;
+			unsigned char ah;
+		} byte;
+	} eax;
+	union {
+		unsigned int ebx;
+		struct {
+			unsigned short bx;
+		} word;
+		struct {
+			unsigned char bl;
+			unsigned char bh;
+		} byte;
+	} ebx;
+	union {
+		unsigned int ecx;
+		struct {
+			unsigned short cx;
+		} word;
+		struct {
+			unsigned char cl;
+			unsigned char ch;
+		} byte;
+	} ecx;
+	union {
+		unsigned int edx;
+		struct {
+			unsigned short dx;
+		} word;
+		struct {
+			unsigned char dl;
+			unsigned char dh;
+		} byte;
+	} edx;
+	union {
+		unsigned int edi;
+		struct {
+			unsigned short di;
+		} word;
+	} edi;
+	union {
+		unsigned int esi;
+		struct {
+			unsigned short si;
+		} word;
+	} esi;
+} REGS;
+
+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;
+
+typedef struct _HCSinfo {
+	ULONG base;
+	UCHAR vec;
+	UCHAR bios;		/* High byte of BIOS address */
+	USHORT BaseAndBios;	/* high byte: pHcsInfo->bios,low byte:pHcsInfo->base */
+} HCSINFO;
+
+#define TUL_RD(x,y)             (UCHAR)(inb(  (int)((ULONG)(x+y)) ))
+#define TUL_RDLONG(x,y)         (ULONG)(inl((int)((ULONG)(x+y)) ))
+#define TUL_WR(     adr,data)   outb( (UCHAR)(data), (int)(adr))
+#define TUL_WRSHORT(adr,data)   outw( (UWORD)(data), (int)(adr))
+#define TUL_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.1.131/linux/drivers/scsi/imm.c linux/drivers/scsi/imm.c
--- v2.1.131/linux/drivers/scsi/imm.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/scsi/imm.c	Wed Dec 16 12:29:28 1998
@@ -186,7 +186,7 @@
 	    while (imm_hosts[i].p_busy)
 	    {
 		schedule();	/* We are safe to schedule here */
-		if (jiffies > now + 3*HZ)
+		if (time_after(jiffies,now + 3*HZ))
 		{
 		    printk(KERN_ERR "imm%d: failed to claim parport because a "
 			   "pardevice is owning the port for too longtime!\n",
@@ -831,7 +831,7 @@
 	 * If we have been running for more than a full timer tick
 	 * then take a rest.
 	 */
-	if (jiffies > start_jiffies + 1)
+	if (time_after(jiffies,start_jiffies + 1))
 	    return 0;
 
 	/*
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c
--- v2.1.131/linux/drivers/scsi/ini9100u.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ini9100u.c	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,1169 @@
+/**************************************************************************
+ * Initio 9100 device driver for Linux.
+ *
+ * Copyright (c) 1994-1998 Initio Corporation
+ * Copyright (c) 1998 Bas Vermeulen <bvermeul@blackstar.xs4all.nl>
+ * 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.
+ *
+ *************************************************************************
+ *
+ * DESCRIPTION:
+ *
+ * This is the Linux low-level SCSI driver for Initio INI-9X00U/UW SCSI host
+ * adapters
+ *
+ * 08/06/97 hc	- v1.01h
+ *		- Support inic-940 and inic-935
+ * 09/26/97 hc	- v1.01i
+ *		- Make correction from J.W. Schultz suggestion
+ * 10/13/97 hc	- Support reset function
+ * 10/21/97 hc	- v1.01j
+ *		- Support 32 LUN (SCSI 3)
+ * 01/14/98 hc	- v1.01k
+ *		- Fix memory allocation problem
+ * 03/04/98 hc	- v1.01l
+ *		- Fix tape rewind which will hang the system problem
+ *		- Set can_queue to tul_num_scb
+ * 06/25/98 hc	- v1.01m
+ *		- Get it work for kernel version >= 2.1.75
+ *		- Dynamic assign SCSI bus reset holding time in init_tulip()
+ * 07/02/98 hc	- v1.01n
+ *		- Support 0002134A
+ * 08/07/98 hc  - v1.01o
+ *		- Change the tul_abort_srb routine to use scsi_done. <01>
+ * 09/07/98 hl  - v1.02
+ *              - Change the INI9100U define and proc_dir_entry to
+ *                reflect the newer Kernel 2.1.118, but the v1.o1o
+ *                should work with Kernel 2.1.118.
+ * 09/20/98 wh  - v1.02a
+ *              - Support Abort command.
+ *              - Handle reset routine.
+ * 09/21/98 hl  - v1.03
+ *              - remove comments.
+ * 12/09/98 bv	- v1.03a
+ *		- Removed unused code
+ * 12/13/98 bv	- v1.03b
+ *		- Remove cli() locking for kernels >= 2.1.95. This uses
+ *		  spinlocks to serialize access to the pSRB_head and
+ *		  pSRB_tail members of the HCS structure.
+ **************************************************************************/
+
+#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>
+#if LINUX_VERSION_CODE <= CVT_LINUX_VERSION(2,1,92)
+#include <linux/bios32.h>
+#endif
+#include <linux/delay.h>
+#include <linux/sched.h>
+#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 "ini9100u.h"
+#include <linux/stat.h>
+#include <linux/malloc.h>
+#include <linux/config.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 "ini9100u.h"
+#endif
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
+#ifdef CONFIG_PCI
+#include <linux/pci.h>
+#endif
+#endif
+
+#ifdef DEBUG_i91u
+unsigned int i91u_debug = DEBUG_DEFAULT;
+#endif
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = INI9100U;
+#include "scsi_module.c"
+#endif
+
+char *i91uCopyright = "Copyright (C) 1996-98";
+char *i91uInitioName = "by Initio Corporation";
+char *i91uProductName = "INI-9X00U/UW";
+char *i91uVersion = "v1.03b";
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+struct proc_dir_entry proc_scsi_ini9100u =
+{
+	PROC_SCSI_INI9100U, 7, "INI9100U",
+	S_IFDIR | S_IRUGO | S_IXUGO, 2,
+	0, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+#endif
+
+#define TULSZ(sz)     (sizeof(sz) / sizeof(sz[0]))
+#define TUL_RDWORD(x,y)         (short)(inl((int)((ULONG)((ULONG)x+(UCHAR)y)) ))
+
+/* set by i91_setup according to the command line */
+static int setup_called = 0;
+
+static int tul_num_ch = 4;	/* Maximum 4 adapters           */
+static int tul_num_scb;
+static int tul_tag_enable = 1;
+static SCB *tul_scb;
+
+#ifdef DEBUG_i91u
+static int setup_debug = 0;
+#endif
+
+static char *setup_str = (char *) NULL;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr0(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr1(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr2(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr3(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr4(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr5(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr6(int irq, void *dev_id, struct pt_regs *);
+static void i91u_intr7(int irq, void *dev_id, struct pt_regs *);
+#else
+static void i91u_intr0(int irq, struct pt_regs *);
+static void i91u_intr1(int irq, struct pt_regs *);
+static void i91u_intr2(int irq, struct pt_regs *);
+static void i91u_intr3(int irq, struct pt_regs *);
+static void i91u_intr4(int irq, struct pt_regs *);
+static void i91u_intr5(int irq, struct pt_regs *);
+static void i91u_intr6(int irq, struct pt_regs *);
+static void i91u_intr7(int irq, struct pt_regs *);
+#endif
+
+static void i91u_panic(char *msg);
+
+static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
+
+				/* ---- EXTERNAL FUNCTIONS ---- */
+					/* Get total number of adapters */
+extern void init_i91uAdapter_table(void);
+extern int Addi91u_into_Adapter_table(WORD, WORD, BYTE, BYTE, BYTE);
+extern int tul_ReturnNumberOfAdapters(void);
+extern void get_tulipPCIConfig(HCS * pHCB, int iChannel_index);
+extern int init_tulip(HCS * pHCB, SCB * pSCB, int tul_num_scb, BYTE * pbBiosAdr, int reset_time);
+extern SCB *tul_alloc_scb(HCS * pHCB);
+extern int tul_abort_srb(HCS * pHCB, Scsi_Cmnd * pSRB);
+extern void tul_exec_scb(HCS * pHCB, SCB * pSCB);
+extern void tul_release_scb(HCS * pHCB, SCB * pSCB);
+extern void tul_stop_bm(HCS * pHCB);
+extern int tul_reset_scsi(HCS * pCurHcb, int seconds);
+extern int tul_isr(HCS * pHCB);
+extern int tul_reset(HCS * pHCB, Scsi_Cmnd * pSRB, unsigned char target);
+extern int tul_reset_scsi_bus(HCS * pCurHcb);
+extern int tul_device_reset(HCS * pCurHcb, ULONG pSrb, unsigned int target, unsigned int ResetFlags);
+				/* ---- EXTERNAL VARIABLES ---- */
+extern HCS tul_hcs[];
+
+/*
+ *  queue services:
+ */
+/*****************************************************************************
+ Function name  : i91uAppendSRBToQueue
+ 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 i91uAppendSRBToQueue(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  : i91uPopSRBFromQueue
+ 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 *i91uPopSRBFromQueue(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 = 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);
+}
+
+/* called from init/main.c */
+
+void i91u_setup(char *str, int *ints)
+{
+	if (setup_called)
+		i91u_panic("i91u: i91u_setup called twice.\n");
+
+	setup_called = ints[0];
+	setup_str = str;
+
+#ifdef DEBUG_i91u
+	setup_debug = ints[0] >= 1 ? ints[1] : DEBUG_DEFAULT;
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
+int tul_NewReturnNumberOfAdapters(void)
+{
+	struct pci_dev *pDev = NULL;	/* Start from none              */
+	int iAdapters = 0;
+	long dRegValue;
+	WORD wBIOS;
+
+	init_i91uAdapter_table();
+
+	while ((pDev = pci_find_device(INI_VENDOR_ID, I950_DEVICE_ID, pDev)) != NULL) {
+		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
+		wBIOS = (UWORD) (dRegValue & 0xFF);
+		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
+			dRegValue = 0;
+		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
+		if (Addi91u_into_Adapter_table(wBIOS,
+					(pDev->base_address[0] & 0xFFFE),
+					       pDev->irq,
+					       pDev->bus->number,
+					       (pDev->devfn >> 3)
+		    ) == 0)
+			iAdapters++;
+	}
+	while ((pDev = pci_find_device(INI_VENDOR_ID, I940_DEVICE_ID, pDev)) != NULL) {
+		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
+		wBIOS = (UWORD) (dRegValue & 0xFF);
+		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
+			dRegValue = 0;
+		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
+		if (Addi91u_into_Adapter_table(wBIOS,
+					(pDev->base_address[0] & 0xFFFE),
+					       pDev->irq,
+					       pDev->bus->number,
+					       (pDev->devfn >> 3)
+		    ) == 0)
+			iAdapters++;
+	}
+	while ((pDev = pci_find_device(INI_VENDOR_ID, I935_DEVICE_ID, pDev)) != NULL) {
+		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
+		wBIOS = (UWORD) (dRegValue & 0xFF);
+		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
+			dRegValue = 0;
+		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
+		if (Addi91u_into_Adapter_table(wBIOS,
+					(pDev->base_address[0] & 0xFFFE),
+					       pDev->irq,
+					       pDev->bus->number,
+					       (pDev->devfn >> 3)
+		    ) == 0)
+			iAdapters++;
+	}
+	while ((pDev = pci_find_device(INI_VENDOR_ID, 0x0002, pDev)) != NULL) {
+		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
+		wBIOS = (UWORD) (dRegValue & 0xFF);
+		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
+			dRegValue = 0;
+		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
+		if (Addi91u_into_Adapter_table(wBIOS,
+					(pDev->base_address[0] & 0xFFFE),
+					       pDev->irq,
+					       pDev->bus->number,
+					       (pDev->devfn >> 3)
+		    ) == 0)
+			iAdapters++;
+	}
+
+	return (iAdapters);
+}
+
+#else				/* <01> */
+
+/*****************************************************************************
+ Function name	: tul_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 tul_ReturnNumberOfAdapters(void)
+{
+	unsigned int i, iAdapters;
+	unsigned int dRegValue;
+	unsigned short command;
+	WORD wBIOS, wBASE;
+	BYTE bPCIBusNum, bInterrupt, bPCIDeviceNum;
+	struct {
+		unsigned short vendor_id;
+		unsigned short device_id;
+	} const i91u_pci_devices[] =
+	{
+		{INI_VENDOR_ID, I935_DEVICE_ID},
+		{INI_VENDOR_ID, I940_DEVICE_ID},
+		{INI_VENDOR_ID, I950_DEVICE_ID},
+		{INI_VENDOR_ID, I920_DEVICE_ID}
+	};
+
+
+	iAdapters = 0;
+	/*
+	 * PCI-bus probe.
+	 */
+	if (pcibios_present()) {
+#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_i91uAdapter_table();
+		for (i = 0; i < TULSZ(i91u_pci_devices); i++) {
+#if LINUX_VERSION_CODE > CVT_LINUX_VERSION(2,1,92)
+			pdev = NULL;
+			while ((pdev = pci_find_device(i91u_pci_devices[i].vendor_id,
+					   i91u_pci_devices[i].device_id,
+						       pdev)))
+#else
+			index = 0;
+			while (!(pcibios_find_device(i91u_pci_devices[i].vendor_id,
+					   i91u_pci_devices[i].device_id,
+					 index++, &pci_bus, &pci_devfn)))
+#endif
+			{
+				if (i == 0) {
+					/*
+					   printk("i91u: The RAID controller is not supported by\n");
+					   printk("i91u:         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\ri91u: tulip 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\ri91u: tulip 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 = TUL_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 (Addi91u_into_Adapter_table(wBIOS, wBASE, bInterrupt, bPCIBusNum,
+						   bPCIDeviceNum) == 0x0)
+						iAdapters++;
+				}
+			}	/* while(pdev=....) */
+		}		/* for PCI_DEVICES */
+	}			/* PCI BIOS present */
+	return (iAdapters);
+}
+#endif
+
+int i91u_detect(Scsi_Host_Template * tpnt)
+{
+	SCB *pSCB;
+	HCS *pHCB;
+	struct Scsi_Host *hreg;
+	unsigned long 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_ini9100u;
+#endif
+
+	if (setup_called) {	/* Setup by i91u_setup          */
+		printk("i91u: processing commandline: ");
+
+#ifdef DEBUG_i91u
+		if (setup_called > 1) {
+			printk("\ni91u: %s\n", setup_str);
+			printk("i91u: usage: i91u[=<DEBUG>]\n");
+			i91u_panic("i91u panics in line %d", __LINE__);
+		}
+		i91u_debug = setup_debug;
+#endif
+	}
+	/* Get total number of adapters in the motherboard */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,93)
+#ifdef CONFIG_PCI
+	iAdapters = tul_NewReturnNumberOfAdapters();
+#else
+	iAdapters = tul_ReturnNumberOfAdapters();
+#endif
+#else
+	iAdapters = tul_ReturnNumberOfAdapters();
+#endif
+
+	if (iAdapters == 0)	/* If no tulip founded, return */
+		return (0);
+
+	tul_num_ch = (iAdapters > tul_num_ch) ? tul_num_ch : iAdapters;
+	/* Update actually channel number */
+	if (tul_tag_enable) {	/* 1.01i                  */
+		tul_num_scb = MAX_TARGETS * i91u_MAXQUEUE;
+	} else {
+		tul_num_scb = MAX_TARGETS + 3;	/* 1-tape, 1-CD_ROM, 1- extra */
+	}			/* Update actually SCBs per adapter */
+
+	/* Get total memory needed for HCS */
+	i = tul_num_ch * sizeof(HCS);
+	memset((unsigned char *) &tul_hcs[0], 0, i);	/* Initialize tul_hcs 0 */
+	/* Get total memory needed for SCB */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+	for (; tul_num_scb >= MAX_TARGETS + 3; tul_num_scb--) {
+		i = tul_num_ch * tul_num_scb * sizeof(SCB);
+		if ((tul_scb = (SCB *) kmalloc(i, GFP_ATOMIC | GFP_DMA)) != NULL)
+			break;
+	}
+#else
+	i = tul_num_ch * tul_num_scb * sizeof(SCB);
+	tul_scb = (SCB *) scsi_init_malloc(i, GFP_ATOMIC | GFP_DMA);
+#endif
+	if (tul_scb == NULL) {
+		printk("i91u: SCB memory allocation error\n");
+		return (0);
+	}
+	memset((unsigned char *) tul_scb, 0, i);
+
+	pSCB = tul_scb;
+	for (i = 0; i < tul_num_ch * tul_num_scb; i++, pSCB++) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		pSCB->SCB_SGPAddr = (U32) VIRT_TO_BUS(&pSCB->SCB_SGList[0]);
+#else
+		pSCB->SCB_SGPAddr = (U32) (&pSCB->SCB_SGList[0]);
+#endif
+	}
+
+	for (i = 0, pHCB = &tul_hcs[0];		/* Get pointer for control block */
+	     i < tul_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
+		request_region(pHCB->HCS_Base, 0x100, "i91u");	/* Register */
+
+		get_tulipPCIConfig(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
+
+		init_tulip(pHCB, tul_scb + (i * tul_num_scb), tul_num_scb, pbBiosAdr, 10);
+		pHCB->HCS_Index = i;	/* 7/29/98 */
+		hreg = scsi_register(tpnt, sizeof(HCS));
+		hreg->io_port = pHCB->HCS_Base;
+		hreg->n_io_port = 0xff;
+		hreg->can_queue = tul_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->irq = pHCB->HCS_Intr;
+		hreg->this_id = pHCB->HCS_SCSI_ID;	/* Assign HCS index           */
+		hreg->base = (UCHAR *) pHCB;
+		hreg->sg_tablesize = TOTAL_SG_ENTRY;	/* Maximun support is 32 */
+
+		/* Initial tulip chip           */
+		switch (i) {
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		case 0:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr0, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 1:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr1, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 2:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr2, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 3:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr3, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 4:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr4, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 5:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr5, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 6:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr6, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		case 7:
+			ok = request_irq(pHCB->HCS_Intr, i91u_intr7, SA_INTERRUPT | SA_SHIRQ, "i91u", NULL);
+			break;
+		default:
+			i91u_panic("i91u: Too many host adapters\n");
+			break;
+		}
+		if (ok < 0) {
+			if (ok == -EINVAL) {
+				printk("i91u: bad IRQ %d.\n", pHCB->HCS_Intr);
+				printk("         Contact author.\n");
+			} else if (ok == -EBUSY)
+				printk("i91u: IRQ %d already in use. Configure another.\n",
+				       pHCB->HCS_Intr);
+			else {
+				printk("\ni91u: Unexpected error code on requesting IRQ %d.\n",
+				       pHCB->HCS_Intr);
+				printk("         Contact author.\n");
+			}
+			i91u_panic("i91u: driver needs an IRQ.\n");
+		}
+#endif
+	}
+
+	tpnt->this_id = -1;
+	tpnt->can_queue = 1;
+
+	return 1;
+}
+
+static void i91uBuildSCB(HCS * pHCB, SCB * pSCB, Scsi_Cmnd * SCpnt)
+{				/* Create corresponding SCB     */
+	struct scatterlist *pSrbSG;
+	SG *pSG;		/* Pointer to SG list           */
+	int i;
+	long TotalLen;
+
+	pSCB->SCB_Post = i91uSCBPost;	/* i91u's callback routine      */
+	pSCB->SCB_Srb = SCpnt;
+	pSCB->SCB_Opcode = ExecSCSI;
+	pSCB->SCB_Flags = SCF_POST;	/* After SCSI done, call post routine */
+	pSCB->SCB_Target = SCpnt->target;
+	pSCB->SCB_Lun = SCpnt->lun;
+	pSCB->SCB_Ident = SCpnt->lun | DISC_ALLOW;
+	pSCB->SCB_Flags |= SCF_SENSE;	/* Turn on auto request sense   */
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+	pSCB->SCB_SensePtr = (U32) VIRT_TO_BUS(SCpnt->sense_buffer);
+#else
+	pSCB->SCB_SensePtr = (U32) (SCpnt->sense_buffer);
+#endif
+
+	pSCB->SCB_SenseLen = SENSE_SIZE;
+
+	pSCB->SCB_CDBLen = SCpnt->cmd_len;
+	pSCB->SCB_HaStat = 0;
+	pSCB->SCB_TaStat = 0;
+	memcpy(&pSCB->SCB_CDB[0], &SCpnt->cmnd, SCpnt->cmd_len);
+
+	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               */
+	}
+
+	if (SCpnt->use_sg) {
+		pSrbSG = (struct scatterlist *) SCpnt->request_buffer;
+		if (SCpnt->use_sg == 1) {	/* If only one entry in the list *//*      treat it as regular I/O */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+			pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(pSrbSG->address);
+#else
+			pSCB->SCB_BufPtr = (U32) (pSrbSG->address);
+#endif
+			TotalLen = pSrbSG->length;
+			pSCB->SCB_SGLen = 0;
+		} else {	/* Assign SG physical address   */
+			pSCB->SCB_BufPtr = pSCB->SCB_SGPAddr;
+			pSCB->SCB_Flags |= SCF_SG;	/* Turn on SG list flag       */
+			for (i = 0, TotalLen = 0, pSG = &pSCB->SCB_SGList[0];	/* 1.01g */
+			     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
+				TotalLen += pSG->SG_Len = pSrbSG->length;
+			}
+			pSCB->SCB_SGLen = i;
+		}
+		pSCB->SCB_BufLen = (SCpnt->request_bufflen > TotalLen) ?
+		    TotalLen : SCpnt->request_bufflen;
+	} else {		/* Non SG                       */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+		pSCB->SCB_BufPtr = (U32) VIRT_TO_BUS(SCpnt->request_buffer);
+#else
+		pSCB->SCB_BufPtr = (U32) (SCpnt->request_buffer);
+#endif
+		pSCB->SCB_BufLen = SCpnt->request_bufflen;
+		pSCB->SCB_SGLen = 0;
+	}
+
+	return;
+}
+
+/* 
+ *  Queue a command and setup interrupts for a free bus.
+ */
+int i91u_queue(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *))
+{
+	register SCB *pSCB;
+	HCS *pHCB;		/* Point to Host adapter control block */
+
+	if (SCpnt->lun > 16) {	/* 07/22/98 */
+
+		SCpnt->result = (DID_TIME_OUT << 16);
+		done(SCpnt);	/* Notify system DONE           */
+		return (0);
+	}
+	pHCB = (HCS *) SCpnt->host->base;
+
+	SCpnt->scsi_done = done;
+	/* Get free SCSI control block  */
+	if ((pSCB = tul_alloc_scb(pHCB)) == NULL) {
+		i91uAppendSRBToQueue(pHCB, SCpnt);	/* Buffer this request  */
+		return (0);
+	}
+	i91uBuildSCB(pHCB, pSCB, SCpnt);
+	tul_exec_scb(pHCB, pSCB);	/* Start execute SCB            */
+	return (0);
+}
+
+/*
+ *  We only support command in interrupt-driven fashion
+ */
+int i91u_command(Scsi_Cmnd * SCpnt)
+{
+	printk("i91u: interrupt driven driver; use i91u_queue()\n");
+	return -1;
+}
+
+/*
+ *  Abort a queued command
+ *  (commands that are on the bus can't be aborted easily)
+ */
+int i91u_abort(Scsi_Cmnd * SCpnt)
+{
+	HCS *pHCB;
+
+	pHCB = (HCS *) SCpnt->host->base;
+	return tul_abort_srb(pHCB, SCpnt);
+}
+
+/*
+ *  Reset registers, reset a hanging bus and
+ *  kill active and disconnected commands for target w/o soft reset
+ */
+int i91u_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
+{				/* I need Host Control Block Information */
+	HCS *pHCB;
+
+	pHCB = (HCS *) SCpnt->host->base;
+
+	if (reset_flags & (SCSI_RESET_SUGGEST_BUS_RESET | SCSI_RESET_SUGGEST_HOST_RESET))
+		return tul_reset_scsi_bus(pHCB);
+	else
+		return tul_device_reset(pHCB, (ULONG) SCpnt, SCpnt->target, reset_flags);
+}
+
+/*
+ * Return the "logical geometry"
+ */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+int i91u_biosparam(Scsi_Disk * disk, kdev_t dev, int *info_array)
+#else
+int i91u_biosparam(Scsi_Disk * disk, int dev, int *info_array)
+#endif
+{
+	HCS *pHcb;		/* Point to Host adapter control block */
+	TCS *pTcb;
+
+	pHcb = (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;
+		}
+	}
+
+#if defined(DEBUG_BIOSPARAM)
+	if (i91u_debug & debug_biosparam) {
+		printk("bios geometry: head=%d, sec=%d, cyl=%d\n",
+		       info_array[0], info_array[1], info_array[2]);
+		printk("WARNING: check, if the bios geometry is correct.\n");
+	}
+#endif
+
+	return 0;
+}
+
+/*****************************************************************************
+ Function name  : i91uSCBPost
+ Description    : This is callback routine be called when tulip finish one
+			SCSI command.
+ Input          : pHCB  -       Pointer to host adapter control block.
+		  pSCB  -       Pointer to SCSI control block.
+ Output         : None.
+ Return         : None.
+*****************************************************************************/
+static void i91uSCBPost(BYTE * pHcb, BYTE * pScb)
+{
+	Scsi_Cmnd *pSRB;	/* Pointer to SCSI request block */
+	HCS *pHCB;
+	SCB *pSCB;
+
+	pHCB = (HCS *) pHcb;
+	pSCB = (SCB *) pScb;
+	if ((pSRB = pSCB->SCB_Srb) == 0) {
+		printk("i91uSCBPost: SRB pointer is empty\n");
+
+		tul_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+		return;
+	}
+	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 SCB Operation Code. */
+
+	default:
+		printk("ini9100u: %x %x\n", pSCB->SCB_HaStat, pSCB->SCB_TaStat);
+		pSCB->SCB_HaStat = DID_ERROR;	/* Couldn't find any better */
+		break;
+	}
+
+	pSRB->result = pSCB->SCB_TaStat | (pSCB->SCB_HaStat << 16);
+
+	if (pSRB == NULL) {
+		printk("pSRB is NULL\n");
+	}
+	pSRB->scsi_done(pSRB);	/* Notify system DONE           */
+	if ((pSRB = i91uPopSRBFromQueue(pHCB)) != NULL)
+		/* Find the next pending SRB    */
+	{			/* Assume resend will success   */
+		/* Reuse old SCB                */
+		i91uBuildSCB(pHCB, pSCB, pSRB);		/* Create corresponding SCB     */
+
+		tul_exec_scb(pHCB, pSCB);	/* Start execute SCB            */
+	} else {		/* No Pending SRB               */
+		tul_release_scb(pHCB, pSCB);	/* Release SCB for current channel */
+	}
+	return;
+}
+
+/*
+ * Interrupts handler (main routine of the driver)
+ */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr0(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr0(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[0].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[0]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr1(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr1(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[1].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[1]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr2(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr2(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[2].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[2]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr3(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr3(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[3].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[3]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr4(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr4(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[4].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[4]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr5(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr5(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[5].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[5]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr6(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr6(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[6].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[6]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1,3,0)
+static void i91u_intr7(int irqno, void *dev_id, struct pt_regs *regs)
+#else
+static void i91u_intr7(int irqno, struct pt_regs *regs)
+#endif
+{
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	unsigned long flags;
+#endif
+
+	if (tul_hcs[7].HCS_Intr != irqno)
+		return;
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_lock_irqsave(&io_request_lock, flags);
+#endif
+
+	tul_isr(&tul_hcs[7]);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spin_unlock_irqrestore(&io_request_lock, flags);
+#endif
+}
+
+/* 
+ * Dump the current driver status and panic...
+ */
+static void i91u_panic(char *msg)
+{
+	printk("\ni91u_panic: %s\n", msg);
+	panic("i91u panic");
+}
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h
--- v2.1.131/linux/drivers/scsi/ini9100u.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/ini9100u.h	Tue Dec 22 10:46:20 1998
@@ -0,0 +1,334 @@
+/**************************************************************************
+ * Initio 9100 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: ini9100u.h
+ * Description: INI-9100U/UW LINUX device driver header
+ * Revision History:
+ * 06/18/96 Harry Chen, Initial Version 1.00A (Beta)
+ * 06/23/98 hc	- v1.01k
+ *		- Get it work for kernel version >= 2.1.75
+ * 12/09/98 bv	- v1.03a
+ *		- Removed unused code
+ * 12/13/98 bv	- v1.03b
+ *		- Add spinlocks to HCS structure.
+*******************************************************************************/
+
+#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 i91u_detect(Scsi_Host_Template *);
+extern int i91u_command(Scsi_Cmnd *);
+extern int i91u_queue(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
+extern int i91u_abort(Scsi_Cmnd *);
+extern int i91u_reset(Scsi_Cmnd *, unsigned int);
+
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(1, 3, 0)
+extern int i91u_biosparam(Scsi_Disk *, kdev_t, int *);	/*for linux v2.0 */
+extern struct proc_dir_entry proc_scsi_ini9100u;
+#else
+extern int i91u_biosparam(Disk *, int, int *);	/*for linux v1.13 */
+#endif
+
+#define i91u_REVID "Initio INI-9X00U/UW SCSI device driver; Revision: 1.03b"
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(1, 3, 0)
+#define INI9100U	{ \
+		NULL, \
+		NULL, \
+		i91u_REVID, \
+		i91u_detect, \
+		NULL, \
+		NULL, \
+		i91u_command, \
+		i91u_queue, \
+		i91u_abort, \
+		i91u_reset, \
+		NULL, \
+		i91u_biosparam, \
+		1, \
+		7, \
+		SG_ALL, \
+		1, \
+		0, \
+		0, \
+		ENABLE_CLUSTERING \
+}
+#else
+
+#if LINUX_VERSION_CODE < CVT_LINUX_VERSION(2, 1, 75)
+#define INI9100U	{ \
+		NULL, \
+		NULL, \
+		&proc_scsi_ini9100u, \
+		NULL, \
+		i91u_REVID, \
+		i91u_detect, \
+		NULL, \
+		NULL, \
+		i91u_command, \
+		i91u_queue, \
+		i91u_abort, \
+		i91u_reset, \
+		NULL, \
+		i91u_biosparam, \
+		1, \
+		7, \
+		SG_ALL, \
+		1, \
+		0, \
+		0, \
+		ENABLE_CLUSTERING \
+}
+#else				/* Version >= 2.1.75 */
+#define INI9100U	{ \
+	next:		NULL,						\
+	module:		NULL,						\
+	proc_dir:	&proc_scsi_ini9100u, \
+	proc_info:	NULL,				\
+	name:		i91u_REVID, \
+	detect:		i91u_detect, \
+	release:	NULL, \
+	info:		NULL,					\
+	command:	i91u_command, \
+	queuecommand:	i91u_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:		i91u_abort, \
+	reset:		i91u_reset, \
+	slave_attach:	NULL, \
+	bios_param:	i91u_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 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
+
+#define i91u_MAXQUEUE		2
+#define TOTAL_SG_ENTRY		32
+#define MAX_TARGETS		16
+#define SENSE_SIZE		14
+
+#define INI_VENDOR_ID   0x1101	/* Initio's PCI vendor ID       */
+#define I950_DEVICE_ID	0x9500	/* Initio's inic-950 product ID   */
+#define I940_DEVICE_ID	0x9400	/* Initio's inic-940 product ID   */
+#define I935_DEVICE_ID	0x9401	/* Initio's inic-935 product ID   */
+#define I920_DEVICE_ID	0x0002	/* Initio's other product ID      */
+
+/************************************************************************/
+/*              Scatter-Gather Element Structure                        */
+/************************************************************************/
+typedef struct SG_Struc {
+	U32 SG_Ptr;		/* Data Pointer */
+	U32 SG_Len;		/* Data Length */
+} SG;
+
+/***********************************************************************
+		SCSI Control Block
+************************************************************************/
+typedef struct Scsi_Ctrl_Blk {
+	U32 SCB_InitioReserved[9];	/* 0 */
+
+	UBYTE SCB_Opcode;	/*24 SCB command code */
+	UBYTE SCB_Flags;	/*25 SCB Flags */
+	UBYTE SCB_Target;	/*26 Target Id */
+	UBYTE SCB_Lun;		/*27 Lun */
+	U32 SCB_BufPtr;		/*28 Data Buffer Pointer */
+	U32 SCB_BufLen;		/*2C Data Allocation Length */
+	UBYTE SCB_SGLen;	/*30 SG list # */
+	UBYTE SCB_SenseLen;	/*31 Sense Allocation Length */
+	UBYTE SCB_HaStat;	/*32 */
+	UBYTE SCB_TaStat;	/*33 */
+	UBYTE SCB_CDBLen;	/*34 CDB Length */
+	UBYTE SCB_Ident;	/*35 Identify */
+	UBYTE SCB_TagMsg;	/*36 Tag Message */
+	UBYTE SCB_TagId;	/*37 Queue Tag */
+	UBYTE SCB_CDB[12];	/*38 */
+	U32 SCB_SGPAddr;	/*44 SG List/Sense Buf phy. Addr. */
+	U32 SCB_SensePtr;	/*48 Sense data pointer */
+	void (*SCB_Post) (BYTE *, BYTE *);	/*4C POST routine */
+	Scsi_Cmnd *SCB_Srb;	/*50 SRB Pointer */
+	SG SCB_SGList[TOTAL_SG_ENTRY];	/*54 Start of SG list */
+} SCB;
+
+/* Opcodes of SCB_Opcode */
+#define ExecSCSI        0x1
+#define BusDevRst       0x2
+#define AbortCmd        0x3
+
+/* Bit Definition for SCB_Flags */
+#define SCF_DONE        0x01
+#define SCF_POST        0x02
+#define SCF_SENSE       0x04
+#define SCF_DIR         0x18
+#define SCF_NO_DCHK     0x00
+#define SCF_DIN         0x08
+#define SCF_DOUT        0x10
+#define SCF_NO_XF       0x18
+#define SCF_POLL        0x40
+#define SCF_SG          0x80
+
+/* Error Codes for SCB_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 SCB_TaStat */
+#define TARGET_CHKCOND  0x02
+#define TARGET_BUSY     0x08
+
+/* 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
+
+/***********************************************************************
+		Target Device Control Structure
+**********************************************************************/
+
+typedef struct Tar_Ctrl_Struc {
+	ULONG TCS_InitioReserved;	/* 0 */
+
+	UWORD TCS_DrvFlags;	/* 4 */
+	UBYTE TCS_DrvHead;	/* 6 */
+	UBYTE TCS_DrvSector;	/* 7 */
+} TCS;
+
+/***********************************************************************
+		Target Device Control Structure
+**********************************************************************/
+/* Bit Definition for TCF_DrvFlags */
+#define TCF_DRV_255_63          0x0400
+
+/***********************************************************************
+	      Host Adapter Control Structure
+************************************************************************/
+typedef struct Ha_Ctrl_Struc {
+	UWORD HCS_Base;		/* 00 */
+	UWORD HCS_BIOS;		/* 02 */
+	UBYTE HCS_Intr;		/* 04 */
+	UBYTE HCS_SCSI_ID;	/* 05 */
+	UBYTE HCS_MaxTar;	/* 06 */
+	UBYTE HCS_NumScbs;	/* 07 */
+
+	UBYTE HCS_Flags;	/* 08 */
+	UBYTE HCS_Index;	/* 09 */
+	UBYTE HCS_Reserved[2];	/* 0a */
+	ULONG HCS_InitioReserved[27];	/* 0C */
+	TCS HCS_Tcs[16];	/* 78 -> 16 Targets */
+	Scsi_Cmnd *pSRB_head;	/* SRB save queue header     */
+	Scsi_Cmnd *pSRB_tail;	/* SRB save queue tail       */
+#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95)
+	spinlock_t HCS_AvailLock;
+	spinlock_t HCS_SemaphLock;
+	spinlock_t pSRB_lock;
+#endif
+} HCS;
+
+/* Bit Definition for HCB_Flags */
+#define HCF_EXPECT_RESET        0x10
+
+/* SCSI related definition                                              */
+#define DISC_NOT_ALLOW          0x80	/* Disconnect is not allowed    */
+#define DISC_ALLOW              0xC0	/* Disconnect is allowed        */
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/mac_esp.c linux/drivers/scsi/mac_esp.c
--- v2.1.131/linux/drivers/scsi/mac_esp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/mac_esp.c	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,691 @@
+/*
+ * 68k mac 53c9[46] scsi driver
+ *
+ * copyright (c) 1998, David Weis weisd3458@uni.edu
+ *
+ * debugging on Quadra 800 and 660AV Michael Schmitz, Dave Kilzer 7/98
+ *
+ * based loosely on cyber_esp.c
+ */
+
+/* these are unused for now */
+#define myreadl(addr) (*(volatile unsigned int *) (addr))
+#define mywritel(b, addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "mac_esp.h"
+
+#include "../../arch/m68k/mac/via6522.h"  /* huh? */
+
+#include <asm/io.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/macints.h>
+#include <asm/machw.h>
+
+#include <asm/pgtable.h>
+
+#include <asm/macintosh.h>
+
+extern inline void esp_handle(struct NCR_ESP *esp);
+extern void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs);
+
+static int  dma_bytes_sent(struct NCR_ESP * esp, int fifo_count);
+static int  dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd *sp);
+static void dma_dump_state(struct NCR_ESP * esp);
+static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length);
+static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length);
+static void dma_ints_off(struct NCR_ESP * esp);
+static void dma_ints_on(struct NCR_ESP * esp);
+static int  dma_irq_p(struct NCR_ESP * esp);
+static int  dma_irq_p_quick(struct NCR_ESP * esp);
+static void dma_led_off(struct NCR_ESP * esp);
+static void dma_led_on(struct NCR_ESP *esp);
+static int  dma_ports_p(struct NCR_ESP *esp);
+static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write);
+static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write);
+
+
+static int esp_dafb_dma_irq_p(struct NCR_ESP * espdev);
+static int esp_iosb_dma_irq_p(struct NCR_ESP * espdev);
+
+static int esp_initialized = 0;
+
+static int setup_num_esps = -1;
+static int setup_disconnect = -1;
+static int setup_nosync = -1;
+static int setup_can_queue = -1;
+static int setup_cmd_per_lun = -1;
+static int setup_sg_tablesize = -1;
+#ifdef SUPPORT_TAGS
+static int setup_use_tagged_queuing = -1;
+#endif
+static int setup_hostid = -1;
+
+/*
+ * Experimental ESP inthandler; check macints.c to make sure dev_id is 
+ * set up properly!
+ */
+
+void mac_esp_intr(int irq, void *dev_id, struct pt_regs *pregs)
+{
+	struct NCR_ESP *esp = (struct NCR_ESP *) dev_id;
+	int irq_p = 0;
+
+	/* Handle the one ESP interrupt showing at this IRQ level. */
+	if(((esp)->irq & 0xff) == irq) {
+	/*
+	 * Debug ..
+	 */
+		irq_p = esp->dma_irq_p(esp);
+	 	printk("mac_esp: irq_p %x current %p disconnected %p\n",
+	 		irq_p, esp->current_SC, esp->disconnected_SC);
+	 		
+		/*
+		 * Mac: if we're here, it's an ESP interrupt for sure!
+		 */
+		if((esp->current_SC || esp->disconnected_SC)) {
+			esp->dma_ints_off(esp);
+
+			ESPIRQ(("I%d(", esp->esp_id));
+			esp_handle(esp);
+			ESPIRQ((")"));
+
+			esp->dma_ints_on(esp);
+		}
+	}
+}
+
+/*
+ * Debug hooks; use for playing with the interrupt flag testing and interrupt
+ * acknowledge on the various machines
+ */
+
+void scsi_esp_polled(int irq, void *dev_id, struct pt_regs *pregs)
+{
+	if (esp_initialized == 0)
+		return;
+
+	mac_esp_intr(irq, dev_id, pregs);
+}
+
+void fake_intr(int irq, void *dev_id, struct pt_regs *pregs)
+{
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: got irq\n");
+#endif
+
+	mac_esp_intr(irq, dev_id, pregs);
+}
+
+void fake_drq(int irq, void *dev_id, struct pt_regs *pregs)
+{
+	printk("mac_esp: got drq\n");
+}
+
+#define DRIVER_SETUP
+
+/*
+ * Function : mac_scsi_setup(char *str, int *ints)
+ *
+ * Purpose : booter command line initialization of the overrides array,
+ *
+ * Inputs : str - unused, ints - array of integer parameters with ints[0]
+ *	equal to the number of ints.
+ *
+ * Currently unused in the new driver; need to add settable parameters to the 
+ * detect function.
+ *
+ */
+
+void mac_esp_setup(char *str, int *ints) {
+#ifdef DRIVER_SETUP
+	/* Format of mac53c9x parameter is:
+	 *   mac53c9x=<num_esps>,<disconnect>,<nosync>,<can_queue>,<cmd_per_lun>,<sg_tablesize>,<hostid>,<use_tags>
+	 * Negative values mean don't change.
+	 */
+	
+	/* Grmbl... the standard parameter parsing can't handle negative numbers
+	 * :-( So let's do it ourselves!
+	 */
+
+	int i = ints[0]+1, fact;
+
+	while( str && (isdigit(*str) || *str == '-') && i <= 10) {
+		if (*str == '-')
+			fact = -1, ++str;
+		else
+			fact = 1;
+		ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
+		if ((str = strchr( str, ',' )) != NULL)
+			++str;
+	}
+	ints[0] = i-1;
+	
+	if (ints[0] < 1) {
+		printk( "mac_esp_setup: no arguments!\n" );
+		return;
+	}
+
+	if (ints[0] >= 1) {
+		if (ints[1] > 0)
+			/* no limits on this, just > 0 */
+		if (ints[1] >= 0 && ints[1] <= 2)
+			setup_num_esps = ints[1];
+		else if (ints[1] > 2)
+			printk( "mac_esp_setup: invalid number of hosts %d !\n", ints[1] );
+	}
+	if (ints[0] >= 2) {
+		if (ints[2] > 0)
+			setup_disconnect = ints[2];
+	}
+	if (ints[0] >= 3) {
+		if (ints[3] >= 0) {
+			setup_nosync = ints[3];
+		}
+	}
+	if (ints[0] >= 4) {
+		if (ints[4] > 0)
+			/* no limits on this, just > 0 */
+			setup_can_queue = ints[4];
+	}
+	if (ints[0] >= 5) {
+		if (ints[5] > 0)
+			setup_cmd_per_lun = ints[5];
+	}
+	if (ints[0] >= 6) {
+		if (ints[6] >= 0) {
+			setup_sg_tablesize = ints[6];
+			/* Must be <= SG_ALL (255) */
+			if (setup_sg_tablesize > SG_ALL)
+				setup_sg_tablesize = SG_ALL;
+		}
+	}
+	if (ints[0] >= 7) {
+		/* Must be between 0 and 7 */
+		if (ints[7] >= 0 && ints[7] <= 7)
+			setup_hostid = ints[7];
+		else if (ints[7] > 7)
+			printk( "mac_esp_setup: invalid host ID %d !\n", ints[7] );
+	}
+#ifdef SUPPORT_TAGS
+	if (ints[0] >= 8) {
+		if (ints[8] >= 0)
+			setup_use_tagged_queuing = !!ints[8];
+	}
+#endif
+#endif
+}
+
+/*
+ * ESP address 'detection'
+ */
+
+unsigned long get_base(int chip_num)
+{
+	/*
+	 * using the chip_num and mac model, figure out where the
+	 * chips are mapped
+	 */
+
+	unsigned long io_base = 0x50f00000;
+	unsigned int second_offset = 0x402;
+	unsigned long scsi_loc = 0;
+
+	switch (macintosh_config->scsi_type) {
+
+	/* 950, 900, 700 */
+	case MAC_SCSI_QUADRA2:
+		scsi_loc =  io_base + 0xf000 + ((chip_num == 0) ? 0 : second_offset);
+		break;
+
+	/* av's */
+	case MAC_SCSI_QUADRA3:
+		scsi_loc = io_base + 0x18000 + ((chip_num == 0) ? 0 : second_offset);
+		break;
+
+	/* most quadra/centris models are like this */	
+	case MAC_SCSI_QUADRA:
+		scsi_loc = io_base + 0x10000;
+		break;
+
+	default:
+		printk("mac_esp: get_base: hit default!\n");
+		scsi_loc = io_base + 0x10000;
+		break;
+
+	} /* switch */
+
+	printk("mac_esp: io base at 0x%lx\n", scsi_loc);
+
+	return scsi_loc;
+}
+
+/*
+ * Model dependent ESP setup
+ */
+
+int mac_esp_detect(Scsi_Host_Template * tpnt)
+{
+	int quick = 0;
+	int chipnum, chipspresent = 0;
+#if 0
+	unsigned long timeout;
+#endif
+
+	/* what do we have in this machine... */
+	if (MACHW_PRESENT(MAC_SCSI_96)) {
+		chipspresent ++;
+	}
+
+	if (MACHW_PRESENT(MAC_SCSI_96_2)) {
+		chipspresent ++;
+	}
+
+	/* number of ESPs present ? */
+	if (setup_num_esps >= 0) {
+	  if (chipspresent >= setup_num_esps)
+	    chipspresent = setup_num_esps;
+	  else
+	    printk("mac_esp_detect: num_hosts detected %d setup %d \n",
+		   chipspresent, setup_num_esps);
+	}
+
+	/* TODO: add disconnect / nosync flags */
+
+	/* setup variables */
+	tpnt->can_queue =
+	  (setup_can_queue > 0) ? setup_can_queue : 7;
+	tpnt->cmd_per_lun =
+	  (setup_cmd_per_lun > 0) ? setup_cmd_per_lun : 1;
+	tpnt->sg_tablesize = 
+	  (setup_sg_tablesize >= 0) ? setup_sg_tablesize : SG_ALL;
+
+	if (setup_hostid >= 0)
+	  tpnt->this_id = setup_hostid;
+	else {
+	  /* use 7 as default */
+	  tpnt->this_id = 7;
+	}
+
+#ifdef SUPPORT_TAGS
+	if (setup_use_tagged_queuing < 0)
+		setup_use_tagged_queuing = DEFAULT_USE_TAGGED_QUEUING;
+#endif
+
+	for (chipnum = 0; chipnum < chipspresent; chipnum ++) {
+		struct NCR_ESP * esp;
+
+		esp = esp_allocate(tpnt, (void *) NULL);
+		esp->eregs = (struct ESP_regs *) get_base(chipnum);
+
+		esp->dma_irq_p = &esp_dafb_dma_irq_p;
+		if (chipnum == 0) {
+
+			if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
+				/* most machines except those below :-) */
+				quick = 1;
+				esp->dma_irq_p = &esp_iosb_dma_irq_p;
+			} else if (macintosh_config->scsi_type == MAC_SCSI_QUADRA3) {
+				/* mostly av's */
+				quick = 0;
+			} else {
+				/* q950, 900, 700 */
+				quick = 1;
+				writel(0x1d1, 0xf9800024);
+				esp->dregs = (void *) 0xf9800024;
+			}
+
+		} else { /* chipnum */
+
+			quick = 1;
+			writel(0x1d1, 0xf9800028);
+			esp->dregs = (void *) 0xf9800028;
+
+		} /* chipnum == 0 */
+
+
+		/* use pio for command bytes; pio for message/data: TBI */
+		esp->do_pio_cmds = 1;
+
+		/* various functions */
+		esp->dma_bytes_sent = &dma_bytes_sent;
+		esp->dma_can_transfer = &dma_can_transfer;
+		esp->dma_dump_state = &dma_dump_state;
+		esp->dma_init_read = NULL;
+		esp->dma_init_write = NULL;
+		esp->dma_ints_off = &dma_ints_off;
+		esp->dma_ints_on = &dma_ints_on;
+
+		esp->dma_ports_p = &dma_ports_p;
+
+
+		/* Optional functions */
+		esp->dma_barrier = NULL;
+		esp->dma_drain = NULL;
+		esp->dma_invalidate = NULL;
+		esp->dma_irq_entry = NULL;
+		esp->dma_irq_exit = NULL;
+		esp->dma_led_on = NULL;
+		esp->dma_led_off = NULL;
+		esp->dma_poll = NULL;
+		esp->dma_reset = NULL;
+
+		/* SCSI chip speed */
+		/* below esp->cfreq = 40000000; */
+
+
+		if (quick) {
+			/* 'quick' means there's handshake glue logic like in the 5380 case */
+			esp->dma_setup = &dma_setup_quick;
+		} else {
+			esp->dma_setup = &dma_setup;
+		}
+
+		if (chipnum == 0) {
+
+			esp->irq = IRQ_MAC_SCSI;
+
+			request_irq(IRQ_MAC_SCSI, esp_intr, 0, "Mac ESP SCSI", esp);
+			request_irq(IRQ_MAC_SCSIDRQ, fake_drq, 0, "Mac ESP DRQ", esp);
+
+			if (macintosh_config->scsi_type == MAC_SCSI_QUADRA) {
+				esp->cfreq = 16500000;
+			} else {
+				esp->cfreq = 25000000;
+			}
+
+
+		} else { /* chipnum == 1 */
+
+			esp->irq = IRQ_MAC_SCSIDRQ;
+
+			request_irq(IRQ_MAC_SCSIDRQ, esp_intr, 0, "Mac ESP SCSI 2", esp);
+
+			esp->cfreq = 25000000;
+
+		}
+
+		if (quick) {
+			printk("esp: using quick version\n");
+		}
+
+		printk("esp: addr at 0x%p\n", esp->eregs);
+
+		esp->scsi_id = 7;
+		esp->diff = 0;
+
+		esp_initialize(esp);
+
+	} /* for chipnum */
+
+	if (chipspresent)
+		printk("\nmac_esp: %d esp controllers found\n", chipspresent);
+
+	esp_initialized = chipspresent;
+
+	return chipspresent;
+}
+
+/*
+ * I've been wondering what this is supposed to do, for some time. Talking 
+ * to Allen Briggs: These machines have an extra register someplace where the
+ * DRQ pin of the ESP can be monitored. That isn't useful for determining 
+ * anything else (such as reselect interrupt or other magic) though. 
+ * Maybe make the semantics should be changed like 
+ * if (esp->current_SC)
+ *	... check DRQ flag ...
+ * else 
+ *	... disconnected, check pending VIA interrupt ...
+ *
+ * There's a problem with using the dabf flag or mac_irq_pending() here: both
+ * seem to return 1 even though no interrupt is currently pending, resulting
+ * in esp_exec_cmd() holding off the next command, and possibly infinite loops
+ * in esp_intr(). 
+ * Short term fix: just use esp_status & ESP_STAT_INTR here, as long as we
+ * use simple PIO. The DRQ status will be important when implementing pseudo
+ * DMA mode (set up ESP transfer count, return, do a batch of bytes in PIO or 
+ * 'hardware handshake' mode upon DRQ).
+ * If you plan on changing this (i.e. to save the esp_status register access in 
+ * favor of a VIA register access or a shadow register for the IFR), make sure
+ * to try a debug version of this first to monitor what registers would be a good
+ * indicator of the ESP interrupt.
+ */
+
+static int esp_dafb_dma_irq_p(struct NCR_ESP * esp)
+{
+	unsigned int ret;
+	int sreg = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: esp_dafb_dma_irq_p dafb %d irq %d\n", 
+		readl(esp->dregs), mac_irq_pending(IRQ_MAC_SCSI));
+#endif
+
+	sreg &= ESP_STAT_INTR;
+
+	/*
+	 * maybe working; this is essentially what's used for iosb_dma_irq_p
+	 */
+	if (sreg)
+		return 1;
+	else
+		return 0;
+
+	/*
+	 * didn't work ...
+	 */
+#if 0
+	if (esp->current_SC)
+		ret = readl(esp->dregs) & 0x200;
+	else if (esp->disconnected_SC)
+		ret = 1; /* sreg ?? */
+	else
+		ret = mac_irq_pending(IRQ_MAC_SCSI);
+
+	return(ret);
+#endif
+
+}
+
+/*
+ * See above: testing mac_irq_pending always returned 8 (SCSI IRQ) regardless 
+ * of the actual ESP status.
+ */
+
+static int esp_iosb_dma_irq_p(struct NCR_ESP * esp)
+{
+	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
+	int sreg = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
+		mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 
+		sreg, esp->current_SC, esp->disconnected_SC);
+#endif
+
+	sreg &= ESP_STAT_INTR;
+
+	if (sreg)
+		return (sreg);
+	else
+		return 0;
+}
+
+/*
+ * This seems to be OK for PIO at least ... usually 0 after PIO.
+ */
+
+static int dma_bytes_sent(struct NCR_ESP * esp, int fifo_count)
+{
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma bytes sent = %x\n", fifo_count);
+#endif
+
+	return fifo_count;
+}
+
+/*
+ * dma_can_transfer is used to switch between DMA and PIO, if DMA (pseudo)
+ * is ever implemented. Returning 0 here will use PIO.
+ */
+
+static int dma_can_transfer(struct NCR_ESP * esp, Scsi_Cmnd * sp)
+{
+	unsigned long sz = sp->SCp.this_residual;
+#if 0	/* no DMA yet; make conditional */
+	if (sz > 0x10000000) {
+		sz = 0x10000000;
+	}
+	printk("mac_esp: dma can transfer = 0lx%x\n", sz);
+#else
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: pio to transfer = %ld\n", sz);
+#endif
+
+	sz = 0;
+#endif
+	return sz;
+}
+
+/*
+ * Not yet ...
+ */
+
+static void dma_dump_state(struct NCR_ESP * esp)
+{
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_dump_state: called\n");
+#endif
+#if 0
+	ESPLOG(("esp%d: dma -- cond_reg<%02x>\n",
+		esp->esp_id, ((struct mac_dma_registers *)
+		(esp->dregs))->cond_reg));
+#endif
+}
+
+/*
+ * DMA setup: should be used to set up the ESP transfer count for pseudo
+ * DMA transfers; need a DRQ transfer function to do the actual transfer
+ */
+
+static void dma_init_read(struct NCR_ESP * esp, char * vaddress, int length)
+{
+	printk("mac_esp: dma_init_read\n");
+}
+
+
+static void dma_init_write(struct NCR_ESP * esp, char * vaddress, int length)
+{
+	printk("mac_esp: dma_init_write\n");
+}
+
+
+static void dma_ints_off(struct NCR_ESP * esp)
+{
+	mac_turnoff_irq(esp->irq);
+}
+
+
+static void dma_ints_on(struct NCR_ESP * esp)
+{
+	mac_turnon_irq(esp->irq);
+}
+
+/*
+ * generic dma_irq_p(), unused
+ */
+
+static int dma_irq_p(struct NCR_ESP * esp)
+{
+	int i = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_irq_p status %d\n", i);
+#endif
+
+	return (i & ESP_STAT_INTR);
+}
+
+static int dma_irq_p_quick(struct NCR_ESP * esp)
+{
+	/*
+	 * Copied from iosb_dma_irq_p()
+	 */
+	int ret  = mac_irq_pending(IRQ_MAC_SCSI) || mac_irq_pending(IRQ_MAC_SCSIDRQ);
+	int sreg = esp->eregs->esp_status;
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_irq_p drq %d irq %d sreg %x curr %p disc %p\n", 
+		mac_irq_pending(IRQ_MAC_SCSIDRQ), mac_irq_pending(IRQ_MAC_SCSI), 
+		sreg, esp->current_SC, esp->disconnected_SC);
+#endif
+
+	sreg &= ESP_STAT_INTR;
+
+	if (sreg)
+		return (sreg);
+	else
+		return 0;
+
+}
+
+static void dma_led_off(struct NCR_ESP * esp)
+{
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_led_off: called\n");
+#endif
+}
+
+
+static void dma_led_on(struct NCR_ESP * esp)
+{
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_led_on: called\n");
+#endif
+}
+
+
+static int dma_ports_p(struct NCR_ESP * esp)
+{
+	return 0;
+}
+
+
+static void dma_setup(struct NCR_ESP * esp, __u32 addr, int count, int write)
+{
+
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_setup\n");
+#endif
+
+	if (write) {
+		dma_init_read(esp, (char *) addr, count);
+	} else {
+		dma_init_write(esp, (char *) addr, count);
+	}
+}
+
+
+static void dma_setup_quick(struct NCR_ESP * esp, __u32 addr, int count, int write)
+{
+#ifdef DEBUG_MAC_ESP
+	printk("mac_esp: dma_setup_quick\n");
+#endif
+}
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/mac_esp.h linux/drivers/scsi/mac_esp.h
--- v2.1.131/linux/drivers/scsi/mac_esp.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/mac_esp.h	Tue Dec 22 10:46:20 1998
@@ -0,0 +1,41 @@
+
+/*
+mac_esp.h
+
+copyright 1997 David Weis, weisd3458@uni.edu
+*/
+
+
+#include "NCR53C9x.h"
+
+#ifndef MAC_ESP_H
+#define MAC_ESP_H
+
+/* #define DEBUG_MAC_ESP */
+
+extern int mac_esp_detect(struct SHT *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+
+
+#define SCSI_MAC_ESP      { proc_dir:		&proc_scsi_esp, \
+			    name:		"Mac 53C9x SCSI", \
+			    detect:		mac_esp_detect, \
+			    release:		NULL, \
+			    info:		esp_info, \
+			    /* command:		esp_command, */ \
+			    queuecommand:	esp_queue, \
+			    abort:		esp_abort, \
+			    reset:		esp_reset, \
+			    can_queue:          7, \
+			    this_id:		7, \
+			    sg_tablesize:	SG_ALL, \
+			    cmd_per_lun:	1, \
+			    use_clustering:	DISABLE_CLUSTERING, \
+			    use_new_eh_code:	0 }
+
+#endif /* MAC_ESP_H */
+
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/mca_53c9x.c linux/drivers/scsi/mca_53c9x.c
--- v2.1.131/linux/drivers/scsi/mca_53c9x.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/mca_53c9x.c	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,476 @@
+/* mca_53c9x.c: Driver for the SCSI adapter found on NCR 35xx
+ *  (and maybe some other) Microchannel machines
+ *
+ * Code taken mostly from Cyberstorm SCSI drivers
+ *   Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
+ *
+ * The CyberStorm SCSI driver (and this driver) is based on David S. Miller's
+ *   ESP driver  * for the Sparc computers. 
+ * 
+ * Special thanks to Ken Stewart at Symbios (LSI) for helping with info on
+ *  the 86C01.  I was on the brink of going ga-ga...
+ *
+ * Also thanks to Jesper Skov for helping me with info on how the Amiga
+ *  does things...
+ */
+
+/*
+ * This is currently only set up to use one 53c9x card at a time; it could be 
+ *  changed fairly easily to detect/use more than one, but I'm not too sure how
+ *  many cards that use the 53c9x on MCA systems there are (if, in fact, there
+ *  are cards that use them, other than the one built into some NCR systems)...
+ *  If anyone requests this, I'll throw it in, otherwise it's not worth the
+ *  effort.
+ */
+
+/*
+ * Info on the 86C01 MCA interface chip at the bottom, if you care enough to
+ *  look.
+ */
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/malloc.h>
+#include <linux/blk.h>
+#include <linux/proc_fs.h>
+#include <linux/stat.h>
+
+#include "scsi.h"
+#include "hosts.h"
+#include "NCR53C9x.h"
+#include "mca_53c9x.h"
+
+#include <asm/dma.h>
+#include <linux/mca.h>
+#include <asm/irq.h>
+#include <asm/mca_dma.h>
+
+#include <asm/pgtable.h>
+
+static int  dma_bytes_sent(struct NCR_ESP *, int);
+static int  dma_can_transfer(struct NCR_ESP *, Scsi_Cmnd *);
+static void dma_dump_state(struct NCR_ESP *);
+static void dma_init_read(struct NCR_ESP *, __u32, int);
+static void dma_init_write(struct NCR_ESP *, __u32, int);
+static void dma_ints_off(struct NCR_ESP *);
+static void dma_ints_on(struct NCR_ESP *);
+static int  dma_irq_p(struct NCR_ESP *);
+static int  dma_ports_p(struct NCR_ESP *);
+static void dma_setup(struct NCR_ESP *, __u32, int, int);
+static void dma_led_on(struct NCR_ESP *);
+static void dma_led_off(struct NCR_ESP *);
+
+/* This is where all commands are put before they are trasfered to the 
+ *  53c9x via PIO.
+ */
+
+volatile unsigned char cmd_buffer[16];
+
+/*
+ * We keep the structure that is used to access the registers on the 53c9x
+ *  here.
+ */
+
+static struct ESP_regs eregs;
+
+/***************************************************************** Detection */
+int mca_esp_detect(Scsi_Host_Template *tpnt)
+{
+	struct NCR_ESP *esp;
+	static int io_port_by_pos[] = MCA_53C9X_IO_PORTS;
+	int mca_53c9x_ids[] = MCA_53C9X_IDS;
+	int *id_to_check = mca_53c9x_ids;
+	int slot;
+	int pos[3];
+	unsigned int tmp_io_addr;
+	unsigned char tmp_byte;
+
+
+	if (!MCA_bus)
+		return 0;
+
+	while (*id_to_check) { 
+		if ((slot = mca_find_adapter(*id_to_check, 0)) !=
+		  MCA_NOTFOUND) 
+		{
+			esp = esp_allocate(tpnt, (void *) NULL);
+
+			pos[0] = mca_read_stored_pos(slot, 2);
+			pos[1] = mca_read_stored_pos(slot, 3);
+			pos[2] = mca_read_stored_pos(slot, 4);
+
+			esp->eregs = &eregs;
+
+			/*
+			 * IO port base is given in the first (non-ID) pos
+			 *  register, like so:
+			 *
+			 *  Bits 3  2  1       IO base
+			 * ----------------------------
+			 *       0  0  0       <disabled>
+			 *       0  0  1       0x0240
+			 *       0  1  0       0x0340
+			 *       0  1  1       0x0400
+			 *       1  0  0       0x0420
+			 *       1  0  1       0x3240
+			 *       1  1  0       0x8240
+			 *       1  1  1       0xA240
+			 */
+
+			tmp_io_addr =
+			  io_port_by_pos[(pos[0] & 0x0E) >> 1];
+
+			esp->eregs->io_addr = tmp_io_addr + 0x10;
+
+      			if (esp->eregs->io_addr == 0x0000) { 
+        			printk("Adapter is disabled.\n");
+				break;
+			}
+
+			/*
+			 * IRQ is specified in bits 4 and 5:
+			 *
+			 *  Bits  4  5        IRQ
+			 * -----------------------
+			 *        0  0         3
+			 *        0  1         5
+			 *        1  0         7
+			 *        1  1         9
+			 */
+
+      			esp->irq = ((pos[0] & 0x30) >> 3) + 3;
+
+			/*
+			 * DMA channel is in the low 3 bits of the second
+			 *  POS register
+			 */
+
+			esp->dma = pos[1] & 7;
+			esp->slot = slot;
+
+			if (request_irq(esp->irq, esp_intr, 0,
+			 "NCR 53c9x SCSI", esp_intr))
+			{
+				printk("Unable to request IRQ %d.\n", esp->irq);
+				return 0;
+			}
+
+ 			if (request_dma(esp->dma, "NCR 53c9x SCSI")) {
+				printk("Unable to request DMA channel %d.\n",
+				 esp->dma);
+				free_irq(esp->irq, esp_intr);
+				return 0;
+			}
+
+			request_region(tmp_io_addr, 32, "NCR 53c9x SCSI");
+
+			/*
+			 * 86C01 handles DMA, IO mode, from address
+			 *  (base + 0x0a)
+			 */
+
+			mca_disable_dma(esp->dma);
+			mca_set_dma_io(esp->dma, tmp_io_addr + 0x0a);
+			mca_enable_dma(esp->dma);
+ 
+			/* Tell the 86C01 to give us interrupts */
+
+			tmp_byte = inb(tmp_io_addr + 0x02) | 0x40;
+			outb(tmp_byte, tmp_io_addr + 0x02); 
+
+			/*
+			 * Scsi ID -- general purpose register, hi
+			 *  2 bits; add 4 to this number to get the
+			 *  ID
+			 */
+
+			esp->scsi_id = ((pos[2] & 0xC0) >> 6) + 4;
+
+			/* Do command transfer with programmed I/O */
+
+			esp->do_pio_cmds = 1;
+
+			/* Required functions */
+
+			esp->dma_bytes_sent = &dma_bytes_sent;
+			esp->dma_can_transfer = &dma_can_transfer;
+			esp->dma_dump_state = &dma_dump_state;
+			esp->dma_init_read = &dma_init_read;
+			esp->dma_init_write = &dma_init_write;
+			esp->dma_ints_off = &dma_ints_off;
+			esp->dma_ints_on = &dma_ints_on;
+			esp->dma_irq_p = &dma_irq_p;
+			esp->dma_ports_p = &dma_ports_p;
+			esp->dma_setup = &dma_setup;
+
+			/* Optional functions */
+
+			esp->dma_barrier = 0;
+			esp->dma_drain = 0;
+			esp->dma_invalidate = 0;
+			esp->dma_irq_entry = 0;
+			esp->dma_irq_exit = 0;
+			esp->dma_led_on = dma_led_on;
+			esp->dma_led_off = dma_led_off;
+			esp->dma_poll = 0;
+			esp->dma_reset = 0;
+
+			/* Set the command buffer */
+
+			esp->esp_command = (volatile unsigned char*)
+			  cmd_buffer;
+	 		esp->esp_command_dvma = virt_to_bus(cmd_buffer);
+
+			/* SCSI chip speed */
+
+			esp->cfreq = 25000000;
+
+			/* Differential SCSI? I think not. */
+
+			esp->diff = 0;
+
+			esp_initialize(esp);
+
+      			printk(" Adapter found in slot %2d: io port 0x%x "
+			  "irq %d dma channel %d\n", slot + 1, tmp_io_addr,
+			   esp->irq, esp->dma);
+
+			mca_set_adapter_name(slot, "NCR 53C9X SCSI Adapter");
+			mca_mark_as_used(slot);
+
+			break;
+		}
+    
+		id_to_check++;
+	}
+
+	return esps_in_use;
+}
+
+
+/******************************************************************* Release */
+
+int mca_esp_release(struct Scsi_Host *host)
+{
+	struct NCR_ESP *esp = (struct NCR_ESP *)host->hostdata;
+	unsigned char tmp_byte;
+
+
+	/*
+	 * Tell the 86C01 to stop sending interrupts
+	 */
+
+	tmp_byte = inb(esp->eregs->io_addr - 0x0E);
+	tmp_byte &= ~0x40;
+	outb(tmp_byte, esp->eregs->io_addr - 0x0E);
+
+	free_irq(esp->irq, esp_intr);
+	free_dma(esp->dma);
+
+	mca_mark_as_unused(esp->eregs->slot);
+
+	return 0;
+}
+
+/************************************************************* DMA Functions */
+static int dma_bytes_sent(struct NCR_ESP *esp, int fifo_count)
+{
+	/* Ask the 53c9x.  It knows. */
+
+	return fifo_count;
+}
+
+static int dma_can_transfer(struct NCR_ESP *esp, Scsi_Cmnd *sp)
+{
+	/* 
+	 * The MCA dma channels can only do up to 128K bytes at a time.
+         *  (16 bit mode)
+	 */
+
+	unsigned long sz = sp->SCp.this_residual;
+	if(sz > 0x20000)
+		sz = 0x20000;
+	return sz;
+}
+
+static void dma_dump_state(struct NCR_ESP *esp)
+{
+	/*
+	 * Doesn't quite match up to the other drivers, but we do what we
+	 *  can.
+	 */
+
+	ESPLOG(("esp%d: dma channel <%d>\n", esp->esp_id, esp->dma));
+	ESPLOG(("bytes left to dma: %d\n", mca_get_dma_residue(esp->dma)));
+}
+
+static void dma_init_read(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	unsigned long flags;
+
+
+	save_flags(flags);
+	cli();
+
+	mca_disable_dma(esp->dma);
+	mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_16 |
+	  MCA_DMA_MODE_IO);
+	mca_set_dma_addr(esp->dma, addr);
+	mca_set_dma_count(esp->dma, length / 2); /* !!! */
+	mca_enable_dma(esp->dma);
+
+	restore_flags(flags);
+}
+
+static void dma_init_write(struct NCR_ESP *esp, __u32 addr, int length)
+{
+	unsigned long flags;
+
+
+	save_flags(flags);
+	cli();
+
+	mca_disable_dma(esp->dma);
+	mca_set_dma_mode(esp->dma, MCA_DMA_MODE_XFER | MCA_DMA_MODE_WRITE |
+	  MCA_DMA_MODE_16 | MCA_DMA_MODE_IO);
+	mca_set_dma_addr(esp->dma, addr);
+	mca_set_dma_count(esp->dma, length / 2); /* !!! */
+	mca_enable_dma(esp->dma);
+
+	restore_flags(flags);
+}
+
+static void dma_ints_off(struct NCR_ESP *esp)
+{
+	/*
+	 * Tell the 'C01 to shut up.  All interrupts are routed through it.
+	 */
+
+	outb(inb(esp->eregs->io_addr - 0x0E) & ~0x40,
+	 esp->eregs->io_addr - 0x0E);
+}
+
+static void dma_ints_on(struct NCR_ESP *esp)
+{
+	/*
+	 * Ok.  You can speak again.
+	 */
+
+	outb(inb(esp->eregs->io_addr - 0x0E) | 0x40,
+	 esp->eregs->io_addr - 0x0E);
+}
+
+static int dma_irq_p(struct NCR_ESP *esp)
+{
+	/*
+	 * DaveM says that this should return a "yes" if there is an interrupt
+	 *  or a DMA error occurred.  I copied the Amiga driver's semantics,
+	 *  though, because it seems to work and we can't really tell if
+	 *  a DMA error happened.  This gives the "yes" if the scsi chip
+	 *  is sending an interrupt and no DMA activity is taking place
+	 */
+
+	return (!(inb(esp->eregs->io_addr - 0x04) & 1) &&
+	 !(inb(esp->eregs->io_addr - 0x04) & 2) ); 
+}
+
+static int dma_ports_p(struct NCR_ESP *esp)
+{
+	/*
+	 * Check to see if interrupts are enabled on the 'C01 (in case abort
+	 *  is entered multiple times, so we only do the abort once)
+	 */
+
+	return (inb(esp->eregs->io_addr - 0x0E) & 0x40) ? 1:0;
+}
+
+static void dma_setup(struct NCR_ESP *esp, __u32 addr, int count, int write)
+{
+	if(write){
+		dma_init_write(esp, addr, count);
+	} else {
+		dma_init_read(esp, addr, count);
+	}
+}
+
+/*
+ * These will not play nicely with other disk controllers that try to use the
+ *  disk active LED... but what can you do?  Don't answer that.
+ *
+ * Stolen shamelessly from ibmmca.c -- IBM Microchannel SCSI adapter driver
+ *
+ */
+
+static void dma_led_on(struct NCR_ESP *esp)
+{
+	outb(inb(PS2_SYS_CTR) | 0xc0, PS2_SYS_CTR);
+}
+
+static void dma_led_off(struct NCR_ESP *esp)
+{
+	outb(inb(PS2_SYS_CTR) & 0x3f, PS2_SYS_CTR);
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = MCA_53C9X;
+#include "scsi_module.c"
+#endif
+
+/*
+ * OK, here's the goods I promised.  The NCR 86C01 is an MCA interface chip 
+ *  that handles enabling/diabling IRQ, dma interfacing, IO port selection
+ *  and other fun stuff.  It takes up 16 addresses, and the chip it is
+ *  connnected to gets the following 16.  Registers are as follows:
+ *
+ * Offsets 0-1 : Card ID
+ *
+ * Offset    2 : Mode enable register --
+ *                Bit    7 : Data Word width (1 = 16, 0 = 8)
+ *		  Bit    6 : IRQ enable (1 = enabled)
+ *                Bits 5,4 : IRQ select
+ *                              0  0 : IRQ 3
+ *			        0  1 : IRQ 5
+ * 				1  0 : IRQ 7
+ *  				1  1 : IRQ 9
+ *                Bits 3-1 : Base Address
+ *                           0  0  0 : <disabled>
+ * 			     0  0  1 : 0x0240
+ *    			     0  1  0 : 0x0340
+ *     			     0  1  1 : 0x0400
+ * 			     1  0  0 : 0x0420
+ * 			     1  0  1 : 0x3240
+ * 			     1  1  0 : 0x8240
+ * 			     1  1  1 : 0xA240
+ *		  Bit    0 : Card enable (1 = enabled)
+ *
+ * Offset    3 : DMA control register --
+ *                Bit    7 : DMA enable (1 = enabled)
+ *                Bits 6,5 : Preemt Count Select (transfers to complete after
+ *                            'C01 has been preempted on MCA bus)
+ *                              0  0 : 0
+ *                              0  1 : 1
+ *                              1  0 : 3
+ *                              1  1 : 7
+ *  (all these wacky numbers; I'm sure there's a reason somewhere)
+ *                Bit    4 : Fairness enable (1 = fair bus priority)
+ *                Bits 3-0 : Arbitration level (0-15 consecutive)
+ * 
+ * Offset    4 : General purpose register
+ *                Bits 7-3 : User definable (here, 7,6 are SCSI ID)
+ *                Bits 2-0 : reserved
+ *
+ * Offset   10 : DMA decode register (used for IO based DMA; also can do
+ *                PIO through this port)
+ *
+ * Offset   12 : Status
+ *                Bits 7-2 : reserved
+ *                Bit    1 : DMA pending (1 = pending)
+ *                Bit    0 : IRQ pending (0 = pending)
+ *
+ * Exciting, huh?  
+ *
+ */                
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/mca_53c9x.h linux/drivers/scsi/mca_53c9x.h
--- v2.1.131/linux/drivers/scsi/mca_53c9x.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/mca_53c9x.h	Tue Dec 22 10:46:20 1998
@@ -0,0 +1,66 @@
+/* mca_53c94.h: Defines and structures for the SCSI adapter found on NCR 35xx
+ *  (and maybe some other) Microchannel machines.
+ *
+ * Code taken mostly from Cyberstorm SCSI drivers
+ *   Copyright (C) 1996 Jesper Skov (jskov@cygnus.co.uk)
+ *
+ * Hacked to work with the NCR MCA stuff by Tymm Twillman (tymm@computer.org)
+ *   1998
+ */
+
+#include "NCR53C9x.h"
+
+#ifndef MCA_53C9X_H
+#define MCA_53C9X_H
+
+/*
+ * From ibmmca.c (IBM scsi controller card driver) -- used for turning PS2 disk
+ *  activity LED on and off
+ */
+
+#define PS2_SYS_CTR	0x92
+
+extern int mca_esp_detect(struct SHT *);
+extern int mca_esp_release(struct Scsi_Host *);
+extern const char *esp_info(struct Scsi_Host *);
+extern int esp_queue(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
+extern int esp_command(Scsi_Cmnd *);
+extern int esp_abort(Scsi_Cmnd *);
+extern int esp_reset(Scsi_Cmnd *, unsigned int);
+extern int esp_proc_info(char *buffer, char **start, off_t offset, int length,
+			 int hostno, int inout);
+
+
+#define MCA_53C9X         { proc_dir:		&proc_scsi_esp, \
+			    name:		"NCR 53c9x SCSI", \
+			    detect:		mca_esp_detect, \
+			    release:		mca_esp_release, \
+			    queuecommand:	esp_queue, \
+			    abort:		esp_abort, \
+			    reset:		esp_reset, \
+			    can_queue:          7, \
+			    sg_tablesize:	SG_ALL, \
+			    cmd_per_lun:	1, \
+                            unchecked_isa_dma:  1, \
+			    use_clustering:	DISABLE_CLUSTERING }
+
+/* Ports the ncr's 53c94 can be put at; indexed by pos register value */
+
+#define MCA_53C9X_IO_PORTS {                             \
+                         0x0000, 0x0240, 0x0340, 0x0400, \
+	                 0x0420, 0x3240, 0x8240, 0xA240, \
+	                }
+			
+/*
+ * Supposedly there were some cards put together with the 'c9x and 86c01.  If
+ *   they have different ID's from the ones on the 3500 series machines, 
+ *   you can add them here and hopefully things will work out.
+ */
+			
+#define MCA_53C9X_IDS {          \
+                         0x7F4C, \
+			 0x0000, \
+                        }
+
+#endif /* MCA_53C9X_H */
+
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/megaraid.c linux/drivers/scsi/megaraid.c
--- v2.1.131/linux/drivers/scsi/megaraid.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/megaraid.c	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,1353 @@
+/*===================================================================
+ *
+ *                    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.
+ *
+ * Version : 0.92
+ * 
+ * Description: Linux device driver for AMI MegaRAID controller
+ *
+ * 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.
+ *
+ * Version 0.91:
+ *     Aligned mailbox area on 16-byte boundry.
+ *     Added schedule() at the end to properly clean up.
+ *     Made improvements for conformity to linux driver standards.
+ *
+ * Version 0.92:
+ *     Added support for 2.1 kernels.
+ *         Reads from pci_dev struct, so it's not dependent on pcibios.
+ *         Added some missing virt_to_bus() translations.
+ *     Added support for SMP.
+ *         Changed global cli()'s to spinlocks for 2.1, and simulated
+ *          spinlocks for 2.0.
+ *     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>
+ *
+ *     Merged with 2.1.131 source tree.
+ *     12 Dec 98       K. Baranowski <kgb@knm.org.pl>
+ *
+ * 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.
+ *
+ *===================================================================*/
+#define QISR 1
+
+#define CRLFSTR "\n"
+
+#define MULTIQ 1
+
+#include <linux/version.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+
+#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");    
+#endif
+#endif
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/proc_fs.h>
+#include <linux/blk.h>
+#include <linux/wait.h>
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+
+#include <linux/sched.h>
+#include <linux/stat.h>
+#include <linux/malloc.h>	/* for kmalloc() */
+#if LINUX_VERSION_CODE < 0x20100
+#include <linux/bios32.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include "sd.h"
+#include "scsi.h"
+#include "hosts.h"
+
+#include "megaraid.h"
+
+/*================================================================
+ *
+ *                          #Defines
+ *
+ *================================================================*/
+
+#if LINUX_VERSION_CODE < 0x020100
+#define ioremap vremap
+#define iounmap vfree
+
+/* simulate spin locks */
+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);\
+                                        cli();}
+#define spin_unlock_irqrestore(x,flags) { (x)->lock=0; restore_flags(flags);}
+
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020100
+#define queue_task_irq(a,b)     queue_task(a,b)
+#define queue_task_irq_off(a,b) queue_task(a,b)
+#endif
+
+#define MAX_SERBUF 160
+#define COM_BASE 0x2f8
+
+#define ENQUEUE(obj,type,list,next) \
+{ type **node; long cpuflag; \
+  spin_lock_irqsave(&mega_lock,cpuflag);\
+  for(node=&(list); *node; node=(type **)&(*node)->##next); \
+  (*node) = obj; \
+  (*node)->##next = NULL; \
+  spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
+
+#define DEQUEUE(obj,type,list,next) \
+{ long cpuflag; \
+  spin_lock_irqsave(&mega_lock,cpuflag);\
+  if ((obj=list) != NULL) {\
+    list = (type *)(list)->##next; \
+  } \
+  spin_unlock_irqrestore(&mega_lock,cpuflag);\
+};
+
+u_long RDINDOOR(mega_host_config *megaCfg)
+{
+  return readl(megaCfg->base + 0x20);
+}
+
+void WRINDOOR(mega_host_config *megaCfg, u_long value)
+{
+  writel(value,megaCfg->base+0x20);
+}
+
+u_long RDOUTDOOR(mega_host_config *megaCfg)
+{
+  return readl(megaCfg->base+0x2C);
+}
+
+void WROUTDOOR(mega_host_config *megaCfg, u_long value)
+{
+  writel(value,megaCfg->base+0x2C);
+}
+
+/*================================================================
+ *
+ *                    Function prototypes
+ *
+ *================================================================*/
+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 void mega_runque(void *);
+static void mega_rundoneq(void);
+static void mega_cmd_done(mega_host_config *,mega_scb *, int);
+
+/* 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, ...);
+#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;
+
+/* Queue of pending/completed SCBs */
+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};
+
+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 void ser_init()
+{
+    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);
+}
+
+static void ser_puts(char *str)
+{
+    char *ptr;
+
+    ser_init();
+    for (ptr=str;*ptr;++ptr)
+        ser_putc(*ptr);
+}
+
+static void ser_putc(char c)
+{
+    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);
+    }
+}
+
+static int ser_printk(const char *fmt, ...)
+{
+    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);
+
+    return i;
+}
+
+#define TRACE(a)    { ser_printk a;}
+
+#else
+#define TRACE(A)
+#endif
+
+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));
+  }
+  SCpnt->scsi_done(SCpnt);
+}
+
+/*-------------------------------------------------------------------------
+ *
+ *                      Local functions
+ *
+ *-------------------------------------------------------------------------*/
+
+/*================================================
+ * Initialize SCB structures
+ *================================================*/
+static void 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;
+  }
+}
+
+/*===========================
+ * Allocate a SCB structure
+ *===========================*/
+static mega_scb *allocateSCB(mega_host_config *megaCfg,Scsi_Cmnd *SCpnt)
+{
+  int        idx;
+  long       flags;
+
+  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;
+      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);
+      }
+
+      return &megaCfg->scbList[idx];
+    }
+  }
+  spin_unlock_irqrestore(&mega_lock,flags);
+
+  printk(KERN_WARNING "Megaraid: Could not allocate free SCB!!!\n");
+  
+  return NULL;
+}
+
+/*=======================
+ * Free a SCB structure
+ *=======================*/
+static void freeSCB(mega_scb *scb)
+{
+  long flags;
+
+  spin_lock_irqsave(&mega_lock,flags);
+  scb->flag  = 0;
+  scb->idx   = -1;
+  scb->next  = NULL;
+  scb->SCpnt = NULL;
+  spin_unlock_irqrestore(&mega_lock,flags);
+}
+
+/* Run through the list of completed requests */
+static void mega_rundoneq()
+{
+  mega_host_config *megaCfg;
+  Scsi_Cmnd        *SCpnt;
+  long              islogical;
+
+  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;
+    if (SCpnt->cmnd[0] == INQUIRY &&
+	((((u_char*)SCpnt->request_buffer)[0] & 0x1F) == TYPE_DISK) &&
+	(islogical != use_raid)) {
+       SCpnt->result = 0xF0;
+    }
+
+    /* Convert result to error */
+    switch(SCpnt->result) {
+    case 0x00: case 0x02:
+      SCpnt->result |= (DID_OK << 16);
+      break;
+    case 0x8:
+      SCpnt->result |= (DID_BUS_BUSY << 16);
+      break;
+    default:
+      SCpnt->result |= (DID_BAD_TARGET << 16);
+      break;
+    }
+
+    /* Callback */
+    callDone(SCpnt);
+  }
+}
+
+/* Add command to the list of completed requests */
+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);
+}
+
+/*----------------------------------------------------
+ * Process pending queue list
+ *
+ * Run as a scheduled task 
+ *----------------------------------------------------*/
+static void mega_runque(void *dummy)
+{
+  mega_host_config *megaCfg;
+  mega_scb         *pScb;
+  long              flags;
+
+  /* Take care of any completed requests */
+  mega_rundoneq();
+
+  DEQUEUE(pScb,mega_scb,qPending,next);
+
+  if (pScb) {
+    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 (MegaIssueCmd(megaCfg, pScb->mboxData, pScb, 1)) {
+      /* We're BUSY... come back later */
+      spin_lock_irqsave(&mega_lock,flags);
+      pScb->next = qPending;
+      qPending   = pScb;
+      spin_unlock_irqrestore(&mega_lock,flags);
+
+      if (!(megaCfg->flag & PENDING)) { /* If PENDING, irq will schedule task */
+          queue_task(&runq, &tq_scheduler);
+      }
+    }
+  }
+}
+
+/*-------------------------------------------------------------------
+ *
+ *                 Build a SCB from a Scsi_Cmnd
+ *
+ * Returns a SCB pointer, or NULL
+ * 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)
+{
+  mega_scb      *pScb;
+  mega_mailbox  *mbox;
+  mega_passthru *pthru;
+  long           seg;
+
+  /* We don't support multi-luns */
+  if (SCpnt->lun != 0) {
+    SCpnt->result = (DID_BAD_TARGET << 16);
+    callDone(SCpnt);
+    return NULL;
+  }
+
+  /*-----------------------------------------------------
+   *
+   *               Logical drive commands
+   *
+   *-----------------------------------------------------*/
+  if (SCpnt->channel == megaCfg->host->max_channel) {
+    switch(SCpnt->cmnd[0]) {
+    case TEST_UNIT_READY:
+      memset(SCpnt->request_buffer, 0, SCpnt->request_bufflen);
+      SCpnt->result = (DID_OK << 16);
+      callDone(SCpnt);
+      return NULL;
+
+    case MODE_SENSE:
+      memset(SCpnt->request_buffer, 0, SCpnt->cmnd[4]);
+      SCpnt->result = (DID_OK << 16);
+      callDone(SCpnt);
+      return NULL;
+
+    case READ_CAPACITY:
+    case INQUIRY:
+      /* Allocate a SCB and initialize passthru */
+      if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+	SCpnt->result = (DID_ERROR << 16);
+	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;
+      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);
+
+      /* Initialize mailbox area */
+      mbox->cmd      = MEGA_MBOXCMD_PASSTHRU;
+      mbox->xferaddr = virt_to_bus(pthru);
+
+      return pScb;
+
+    case READ_6:
+    case WRITE_6:
+    case READ_10:
+    case WRITE_10:
+      /* Allocate a SCB and initialize mailbox */
+      if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+	SCpnt->result = (DID_ERROR << 16);
+	callDone(SCpnt);
+	return NULL;
+      }
+      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) ?
+	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->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->lba =
+	  ((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);
+
+      return pScb;
+      
+    default:
+      SCpnt->result = (DID_BAD_TARGET << 16);
+      callDone(SCpnt);
+      return NULL;
+    }
+  }
+  /*-----------------------------------------------------
+   *
+   *               Passthru drive commands
+   *
+   *-----------------------------------------------------*/
+  else {
+    /* Allocate a SCB and initialize passthru */
+    if ((pScb = allocateSCB(megaCfg,SCpnt)) == NULL) {
+      SCpnt->result = (DID_ERROR << 16);
+      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;
+    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);
+    
+    /* Initialize mailbox */
+    mbox->cmd      = MEGA_MBOXCMD_PASSTHRU;
+    mbox->xferaddr = virt_to_bus(pthru);
+
+    return pScb;
+  }
+  return NULL;
+}
+
+/*--------------------------------------------------------------------
+ * Interrupt service routine
+ *--------------------------------------------------------------------*/
+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;
+
+  megaCfg = (mega_host_config *)devp;
+  mbox    = (mega_mailbox *)megaCfg->mbox;
+
+  if (megaCfg->host->irq == irq) {
+    spin_lock_irqsave(&mega_lock,flags);
+
+    if (megaCfg->flag & IN_ISR) {
+      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);
+    }
+    
+    qCnt    = mbox->numstatus;
+    qStatus = mbox->status;
+
+    if (qCnt > 1) {TRACE(("ISR: Received %d status\n", qCnt))
+        printk(KERN_DEBUG "Got numstatus = %d\n",qCnt);
+    }
+    
+    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);
+      }
+    }
+    if (megaCfg->flag & BOARD_QUARTZ) {
+        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_lock_irqsave(&io_request_lock, flags);
+    mega_runque(NULL);
+    spin_unlock_irqrestore(&io_request_lock,flags);              
+
+#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);
+#endif
+
+  }
+}
+
+/*==================================================*/
+/* Wait until the controller's mailbox is available */
+/*==================================================*/
+static int busyWaitMbox(mega_host_config *megaCfg)
+{
+  mega_mailbox *mbox = (mega_mailbox *)megaCfg->mbox;
+  long          counter;
+
+  for(counter=0; counter<0xFFFFFF; counter++) {
+    if (!mbox->busy) return 0;
+  }
+  return -1;
+}
+
+/*=====================================================
+ * Post a command to the card
+ *
+ * Arguments:
+ *   mega_host_config *megaCfg - Controller structure
+ *   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
+   */
+  if (megaCfg->flag & PENDING) {
+    return -1;
+  }
+
+  /* Wait until mailbox is free */
+  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));
+    }
+    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);
+
+  /* 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);
+    }
+  }
+  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);
+
+      while((cmdDone=RDOUTDOOR(megaCfg)) != 0x10001234);
+      WROUTDOOR(megaCfg, cmdDone);
+
+      if (pScb) {
+	mega_cmd_done(megaCfg,pScb, mbox->status);
+	mega_rundoneq();
+      }
+
+      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);
+      
+      if (pScb) {
+	mega_cmd_done(megaCfg,pScb, mbox->status);
+	mega_rundoneq();
+      }
+      megaCfg->flag &= ~PENDING;
+    }
+  }
+
+  return 0;
+}
+
+/*-------------------------------------------------------------------
+ * Copies data to SGLIST
+ *-------------------------------------------------------------------*/
+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;
+    return 0;
+  }
+
+  sgList = (struct scatterlist *)scb->SCpnt->buffer;
+  if (scb->SCpnt->use_sg == 1) {
+    *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;
+  }
+  
+  /* Reset pointer and length fields */
+  *buffer = virt_to_bus(scb->sgList);
+  *length = 0;
+
+  /* Return count of SG requests */
+  return scb->SCpnt->use_sg;
+}
+    
+/*--------------------------------------------------------------------
+ * 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
+ *   01 01 command id
+ *   02 02 # of sectors
+ *   04 04 logical bus address
+ *   08 04 physical buffer address
+ *   0C 01 logical drive #
+ *   0D 01 length of scatter/gather list
+ *   0E 01 reserved
+ *   0F 01 mailbox busy
+ *   10 01 numstatus byte
+ *   11 01 status byte
+ *--------------------------------------------------------------------*/
+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;
+
+  /* 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);
+  }
+  return 0;
+}
+
+/*-------------------------------------------------------------------
+ * Issue an adapter info query to the controller
+ *-------------------------------------------------------------------*/
+static int mega_i_query_adapter(mega_host_config *megaCfg)
+{
+  mega_RAIDINQ *adapterInfo;
+  mega_mailbox *mbox;
+  u_char        mboxData[16];
+  u_long        paddr;
+
+  spin_lock_init(&mega_lock);
+  /* Initialize adapter inquiry */
+  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);
+
+  /* Initialize mailbox registers */
+  mbox->cmd      = MEGA_MBOXCMD_ADAPTERINQ;
+  mbox->xferaddr = paddr;
+
+  /* Issue a blocking command to the card */
+  MegaIssueCmd(megaCfg, mboxData, NULL, 0);
+  
+  /* Initialize host/local structures with Adapter info */
+  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;
+
+#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("\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);
+#else
+      memcpy(megaCfg->fwVer, adapterInfo->AdpInfo.FwVer, 4);
+      megaCfg->fwVer[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);
+  return 0;
+}
+
+/*-------------------------------------------------------------------------
+ *
+ *                      Driver interface functions
+ *
+ *-------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------
+ * 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)
+{
+  *start = buffer;
+  return 0;
+}
+
+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;
+
+#if LINUX_VERSION_CODE < 0x20100
+  while(!pcibios_find_device(pciVendor, pciDev, pciIdx,&pciBus,&pciDevFun)) {
+#else
+  struct pci_dev   *pdev=pci_devices;
+
+  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));
+    
+    /* 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);
+#else
+    megaBase = pdev->base_address[0];
+    megaIrq = pdev->irq;
+#endif
+    pciIdx++;
+
+    if (flag & BOARD_QUARTZ) {
+      megaBase &= PCI_BASE_ADDRESS_MEM_MASK;
+      megaBase = (long) ioremap(megaBase,128);
+    }
+    else {
+      megaBase &= PCI_BASE_ADDRESS_IO_MASK;
+      megaBase += 0x10;
+    }
+
+    /* 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);
+    
+    /* Copy resource info into structure */
+    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;
+
+    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);
+	continue;
+      }
+      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);
+      continue;
+    }
+
+    mega_register_mailbox(megaCfg, virt_to_bus((void*)&megaCfg->mailbox));
+    mega_i_query_adapter(megaCfg);
+
+    /* Initialize SCBs */
+    initSCB(megaCfg);
+
+  }
+  return pciIdx;
+}
+
+/*---------------------------------------------------------
+ * Detects if a megaraid controller exists in this system
+ *---------------------------------------------------------*/
+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;
+    }
+#endif
+
+  count += findCard(pHostTmpl, 0x101E, 0x9010, 0);
+  count += findCard(pHostTmpl, 0x101E, 0x9060, 0);
+  count += findCard(pHostTmpl, 0x8086, 0x1960, BOARD_QUARTZ);
+
+  return count;
+}
+
+/*---------------------------------------------------------------------
+ * Release the controller's resources
+ *---------------------------------------------------------------------*/
+int megaraid_release(struct Scsi_Host *pSHost)
+{
+  mega_host_config *megaCfg;
+  mega_mailbox         *mbox;
+  u_char                mboxData[16];
+
+  megaCfg = (mega_host_config*)pSHost->hostdata;
+  mbox    = (mega_mailbox *)mboxData;
+
+  /* Flush cache to disk */
+  memset(mbox, 0, 16);
+  mboxData[0] = 0xA;
+
+  /* Issue a blocking (interrupts disabled) command to the card */
+  MegaIssueCmd(megaCfg, mboxData, NULL, 0);
+
+  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);
+
+  return 0;
+}
+
+/*----------------------------------------------
+ * Get information about the card/driver 
+ *----------------------------------------------*/
+const char *megaraid_info(struct Scsi_Host *pSHost)
+{
+  static char           buffer[512];
+  mega_host_config  *megaCfg;
+  mega_RAIDINQ          *adapterInfo;
+
+  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);
+  return buffer;
+}
+
+/*-----------------------------------------------------------------
+ * Perform a SCSI command
+ * Mailbox area:
+ *   00 01 command
+ *   01 01 command id
+ *   02 02 # of sectors
+ *   04 04 logical bus address
+ *   08 04 physical buffer address
+ *   0C 01 logical drive #
+ *   0D 01 length of scatter/gather list
+ *   0E 01 reserved
+ *   0F 01 mailbox busy
+ *   10 01 numstatus byte
+ *   11 01 status byte 
+ *-----------------------------------------------------------------*/
+int megaraid_queue(Scsi_Cmnd *SCpnt, void (*pktComp)(Scsi_Cmnd *))
+{
+  mega_host_config *megaCfg;
+  mega_scb         *pScb;
+
+  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');
+    megaCfg->flag |= (1L << SCpnt->channel);
+  }
+
+  SCpnt->scsi_done = pktComp;
+
+  /* Allocate and build a SCB request */
+  if ((pScb = mega_build_cmd(megaCfg, SCpnt)) != NULL) {
+    /* Add SCB to the head of the pending queue */
+    ENQUEUE(pScb, mega_scb, qPending, next);
+
+    /* Issue the command to the card */
+      mega_runque(NULL);
+  }
+
+  return 0;
+}
+
+/*----------------------------------------------------------------------
+ * 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_errcode = 0;
+
+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
+ */
+ 
+int megaraid_command(Scsi_Cmnd *SCpnt)
+{
+  internal_done_flag = 0;
+
+  /* Queue command, and wait until it has completed */
+  megaraid_queue(SCpnt, internal_done);
+
+  while(!internal_done_flag)
+    barrier();
+
+  return internal_done_errcode;
+}
+
+/*---------------------------------------------------------------------
+ * Abort a previous SCSI request
+ *---------------------------------------------------------------------*/
+int megaraid_abort(Scsi_Cmnd *SCpnt)
+{
+  mega_host_config *megaCfg;
+  int       idx;
+  long      flags;
+
+  spin_lock_irqsave(&mega_lock,flags);
+
+  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));
+  /*
+   * Walk list of SCBs for any that are still outstanding
+   */
+  for(idx=0; idx<megaCfg->max_cmds; idx++) {
+    if (megaCfg->scbList[idx].idx >= 0) {
+      if (megaCfg->scbList[idx].SCpnt == SCpnt) {
+	freeSCB(&megaCfg->scbList[idx]);
+
+	SCpnt->result = (DID_RESET << 16) | (SUGGEST_RETRY<<24);
+	callDone(SCpnt);
+      }
+    }
+  }
+  spin_unlock_irqrestore(&mega_lock,flags);
+  return SCSI_ABORT_SNOOZE;
+}
+
+/*---------------------------------------------------------------------
+ * Reset a previous SCSI request
+ *---------------------------------------------------------------------*/
+int megaraid_reset(Scsi_Cmnd *SCpnt, unsigned int rstflags)
+{
+  mega_host_config *megaCfg;
+  int       idx;
+  long      flags;
+
+  spin_lock_irqsave(&mega_lock,flags);
+
+  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));
+
+  /*
+   * Walk list of SCBs for any that are still outstanding
+   */
+  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);
+    }
+  }
+  spin_unlock_irqrestore(&mega_lock,flags);
+  return SCSI_RESET_PUNT;
+} 
+
+/*-------------------------------------------------------------
+ * Return the disk geometry for a particular disk
+ * Input:
+ *   Disk *disk - Disk geometry
+ *   kdev_t dev - Device node
+ *   int *geom  - Returns geometry fields
+ *     geom[0] = heads
+ *     geom[1] = sectors
+ *     geom[2] = cylinders
+ *-------------------------------------------------------------*/
+int megaraid_biosparam(Disk *disk, kdev_t dev, int *geom)
+{
+  int                   heads, sectors, cylinders;
+  mega_host_config *megaCfg;
+
+  /* Get pointer to host config structure */
+  megaCfg = (mega_host_config *)disk->device->host->hostdata;
+
+  /* Default 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;
+    cylinders = disk->capacity / (heads * sectors);
+  }
+
+  /* return result */
+  geom[0] = heads;
+  geom[1] = sectors;
+  geom[2] = cylinders;
+
+  return 0;
+}
+
+#ifdef MODULE
+Scsi_Host_Template driver_template = MEGARAID;
+
+#include "scsi_module.c"
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/megaraid.h linux/drivers/scsi/megaraid.h
--- v2.1.131/linux/drivers/scsi/megaraid.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/scsi/megaraid.h	Fri Dec 18 10:12:25 1998
@@ -0,0 +1,282 @@
+#ifndef __MEGARAID_H__
+#define __MEGARAID_H__
+
+#define IN_ISR                  0x80000000L
+#define NO_INTR                 0x40000000L
+#define IN_TIMEOUT              0x20000000L
+#define PENDING                 0x10000000L
+#define BOARD_QUARTZ            0x08000000L
+
+#define SCB_ACTIVE 0x1
+#define SCB_WAITQ  0x2
+#define SCB_ISSUED 0x4
+
+#define SCB_FREE                -1
+#define SCB_RESET               -2
+#define SCB_ABORT               -3
+#define SCB_LOCKED              -4
+
+#define MEGA_CMD_TIMEOUT        10
+
+#define MAX_SGLIST              20
+#define MAX_COMMANDS            254
+
+#define MAX_LOGICAL_DRIVES      8
+#define MAX_CHANNEL             5
+#define MAX_TARGET              15
+#define MAX_PHYSICAL_DRIVES     MAX_CHANNEL*MAX_TARGET
+
+#define INQUIRY_DATA_SIZE       0x24
+#define MAX_CDB_LEN             0x0A
+#define MAX_REQ_SENSE_LEN       0x20
+
+#define INTR_VALID              0x40
+
+/* Mailbox commands */
+#define MEGA_MBOXCMD_LREAD      0x01
+#define MEGA_MBOXCMD_LWRITE     0x02
+#define MEGA_MBOXCMD_PASSTHRU   0x03
+#define MEGA_MBOXCMD_ADAPTERINQ 0x05
+
+/* Offsets into Mailbox */
+#define COMMAND_PORT       0x00
+#define COMMAND_ID_PORT    0x01
+#define SG_LIST_PORT0      0x08
+#define SG_LIST_PORT1      0x09
+#define SG_LIST_PORT2      0x0a
+#define SG_LIST_PORT3      0x0b
+#define SG_ELEMENT_PORT    0x0d
+#define NO_FIRED_PORT      0x0f
+
+/* I/O Port offsets */
+#define I_CMD_PORT         0x00
+#define I_ACK_PORT         0x00
+#define I_TOGGLE_PORT      0x01
+#define INTR_PORT          0x0a
+
+#define MAILBOX_SIZE       70
+#define MBOX_BUSY_PORT     0x00
+#define MBOX_PORT0         0x04
+#define MBOX_PORT1         0x05
+#define MBOX_PORT2         0x06
+#define MBOX_PORT3         0x07
+#define ENABLE_MBOX_REGION 0x0B
+
+/* I/O Port Values */
+#define ISSUE_BYTE         0x10
+#define ACK_BYTE           0x08
+#define ENABLE_INTR_BYTE   0xc0
+#define DISABLE_INTR_BYTE  0x00
+#define VALID_INTR_BYTE    0x40
+#define MBOX_BUSY_BYTE     0x10
+#define ENABLE_MBOX_BYTE   0x00
+
+/* Setup some port macros here */
+#define WRITE_MAILBOX(base,offset,value)   *(base+offset)=value
+#define READ_MAILBOX(base,offset)          *(base+offset)
+
+#define WRITE_PORT(base,offset,value)      outb_p(value,base+offset)
+#define READ_PORT(base,offset)             inb_p(base+offset)
+
+#define ISSUE_COMMAND(base)   WRITE_PORT(base,I_CMD_PORT,ISSUE_BYTE)
+#define CLEAR_INTR(base)      WRITE_PORT(base,I_ACK_PORT,ACK_BYTE)
+#define ENABLE_INTR(base)     WRITE_PORT(base,I_TOGGLE_PORT,ENABLE_INTR_BYTE)
+#define DISABLE_INTR(base)    WRITE_PORT(base,I_TOGGLE_PORT,DISABLE_INTR_BYTE)
+
+/* Define AMI's PCI codes */
+#undef PCI_VENDOR_ID_AMI
+#undef PCI_DEVICE_ID_AMI_MEGARAID
+
+#ifndef PCI_VENDOR_ID_AMI
+#define PCI_VENDOR_ID_AMI          0x101E
+#define PCI_DEVICE_ID_AMI_MEGARAID 0x9010
+#endif
+
+#define PCI_CONF_BASE_ADDR_OFFSET  0x10
+#define PCI_CONF_IRQ_OFFSET        0x3c
+
+#if LINUX_VERSION_CODE < 0x20100
+#define MEGARAID \
+  { NULL,                               /* Next                      */\
+    NULL,                               /* Usage Count Pointer       */\
+    NULL,                               /* /proc Directory Entry     */\
+    megaraid_proc_info,                 /* /proc Info Function       */\
+    "MegaRAID",                         /* Driver Name               */\
+    megaraid_detect,                    /* Detect Host Adapter       */\
+    megaraid_release,                   /* Release Host Adapter      */\
+    megaraid_info,                      /* Driver Info Function      */\
+    megaraid_command,                   /* Command Function          */\
+    megaraid_queue,                     /* Queue Command Function    */\
+    megaraid_abort,                     /* Abort Command Function    */\
+    megaraid_reset,                     /* Reset Command Function    */\
+    NULL,                               /* Slave Attach Function     */\
+    megaraid_biosparam,                 /* Disk BIOS Parameters      */\
+    1,                                  /* # of cmds that can be\
+                                           outstanding at any time */\
+    7,                                  /* HBA Target ID             */\
+    MAX_SGLIST,                         /* Scatter/Gather Table Size */\
+    1,                                  /* SCSI Commands per LUN     */\
+    0,                                  /* Present                   */\
+    0,                                  /* Default Unchecked ISA DMA */\
+    ENABLE_CLUSTERING }                 /* Enable Clustering         */
+#else
+#define MEGARAID \
+  {\
+    name:            "MegaRAID",               /* Driver Name               */\
+    proc_info:        megaraid_proc_info,      /* /proc driver info         */\
+    detect:           megaraid_detect,         /* Detect Host Adapter       */\
+    release:          megaraid_release,        /* Release Host Adapter      */\
+    info:             megaraid_info,           /* Driver Info Function      */\
+    command:          megaraid_command,        /* Command Function          */\
+    queuecommand:     megaraid_queue,          /* Queue Command Function    */\
+    abort:            megaraid_abort,          /* Abort Command Function    */\
+    reset:            megaraid_reset,          /* Reset Command Function    */\
+    bios_param:       megaraid_biosparam,      /* Disk BIOS Parameters      */\
+    can_queue:        255,                     /* Can Queue                 */\
+    this_id:          7,                       /* HBA Target ID             */\
+    sg_tablesize:     MAX_SGLIST,              /* Scatter/Gather Table Size */\
+    cmd_per_lun:      1,                       /* SCSI Commands per LUN     */\
+    present:          0,                       /* Present                   */\
+    unchecked_isa_dma:0,                       /* Default Unchecked ISA DMA */\
+    use_clustering:   ENABLE_CLUSTERING       /* Enable Clustering         */\
+  }
+#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];
+} 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];
+} mega_LDRV_INFO;
+
+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;
+} 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;
+} 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];
+} mega_mailbox;
+
+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;
+};
+
+/* 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];
+
+  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 );
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/ppa.c linux/drivers/scsi/ppa.c
--- v2.1.131/linux/drivers/scsi/ppa.c	Fri Oct 23 22:01:21 1998
+++ linux/drivers/scsi/ppa.c	Wed Dec 16 12:29:28 1998
@@ -147,7 +147,7 @@
 	    while (ppa_hosts[i].p_busy)
 	    {
 		schedule();	/* We are safe to schedule here */
-		if (jiffies > now + 3*HZ)
+		if (time_after(jiffies,now + 3*HZ))
 		{
 		    printk(KERN_ERR "ppa%d: failed to claim parport because a "
 			   "pardevice is owning the port for too longtime!\n",
@@ -867,7 +867,7 @@
 	 * If we have been running for more than a full timer tick
 	 * then take a rest.
 	 */
-	if (jiffies > start_jiffies + 1)
+	if (time_after(jiffies,start_jiffies + 1))
 	    return 0;
 
 	if (((r & 0xc0) != 0xc0) || (cmd->SCp.this_residual <= 0)) {
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.1.131/linux/drivers/scsi/scsi.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/scsi/scsi.c	Fri Dec 18 10:12:25 1998
@@ -30,6 +30,8 @@
  *  Leonard N. Zubkoff <lnz@dandelion.com>
  *
  *  Converted cli() code to spinlocks, Ingo Molnar
+ *
+ *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
  */
 
 #include <linux/config.h>
@@ -521,9 +523,18 @@
 
   }
   else {
+    /* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0 */
+    int order_dev;
+    
     for (channel = 0; channel <= shpnt->max_channel; channel++) {
       for (dev = 0; dev < shpnt->max_id; ++dev) {
-        if (shpnt->this_id != dev) {
+        if( shpnt->reverse_ordering)
+        	/* Shift to scanning 15,14,13... or 7,6,5,4, */
+        	order_dev = shpnt->max_channel-dev-1;
+        else
+        	order_dev = dev;
+        	
+        if (shpnt->this_id != order_dev) {
 
           /*
            * We need the for so our continue, etc. work fine. We put this in
@@ -534,7 +545,7 @@
                          max_scsi_luns : shpnt->max_lun);
 	  sparse_lun = 0;
           for (lun = 0; lun < max_dev_lun; ++lun) {
-            if (!scan_scsis_single (channel, dev, lun, &max_dev_lun,
+            if (!scan_scsis_single (channel, order_dev, lun, &max_dev_lun,
 				    &sparse_lun, &SDpnt, SCpnt, shpnt,
 				    scsi_result)
 		&& !sparse_lun)
@@ -1297,7 +1308,7 @@
      */
     timeout = host->last_reset + MIN_RESET_DELAY;
 
-    if (jiffies < timeout) {
+    if (host->resetting && time_before(jiffies, timeout)) {
 	int ticks_remaining = timeout - jiffies;
 	/*
 	 * NOTE: This may be executed from within an interrupt
@@ -1310,7 +1321,7 @@
 	 */
 	spin_unlock_irq(&io_request_lock);
 	while (--ticks_remaining >= 0) mdelay(1+999/HZ);
-	host->last_reset = jiffies - MIN_RESET_DELAY;
+	host->resetting = 0;
 	spin_lock_irq(&io_request_lock);
     }
 
@@ -1367,7 +1378,7 @@
 #ifdef DEBUG_DELAY
 	clock = jiffies + 4 * HZ;
 	spin_unlock_irq(&io_request_lock);
-	while (jiffies < clock) barrier();
+	while (time_before(jiffies, clock)) barrier();
 	spin_lock_irq(&io_request_lock);
 	printk("done(host = %d, result = %04x) : routine at %p\n",
 	       host->host_no, temp, host->hostt->command);
@@ -2743,7 +2754,7 @@
         {
             if(SDpnt->host->hostt == tpnt 
                && SDpnt->host->hostt->module
-               && SDpnt->host->hostt->module->usecount) return;
+               && GET_USE_COUNT(SDpnt->host->hostt->module)) return;
             /* 
              * FIXME(eric) - We need to find a way to notify the
              * low level driver that we are shutting down - via the
@@ -3032,7 +3043,7 @@
     /*
      * If we are busy, this is not going to fly.
      */
-    if(tpnt->module->usecount != 0) return 0;
+    if(GET_USE_COUNT(tpnt->module) != 0) return 0;
 
     /*
      * Next, detach the devices from the driver.
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.1.131/linux/drivers/scsi/scsi_error.c	Tue Jul 28 14:21:08 1998
+++ linux/drivers/scsi/scsi_error.c	Wed Dec 16 12:25:47 1998
@@ -142,7 +142,6 @@
   SCSI_LOG_ERROR_RECOVERY(5,printk("Clearing timer for command %p\n", SCset));
 
   SCset->eh_timeout.data = (unsigned long) NULL;
-  SCset->eh_timeout.expires = 0;
   SCset->eh_timeout.function = NULL;
 
   return rtn;
diff -u --recursive --new-file v2.1.131/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.1.131/linux/drivers/scsi/scsi_obsolete.c	Wed Dec 16 10:32:55 1998
+++ linux/drivers/scsi/scsi_obsolete.c	Wed Dec 16 12:44:21 1998
@@ -607,9 +607,7 @@
 	if ((++SCpnt->retries) < SCpnt->allowed)
 	{
 	    if ((SCpnt->retries >= (SCpnt->allowed >> 1))
-		/* FIXME: last_reset == 0 is allowed */
-                && time_after(jiffies, SCpnt->host->last_reset
-                              + MIN_RESET_PERIOD)
+		&& !(SCpnt->host->resetting && time_before(jiffies, SCpnt->host->last_reset + MIN_RESET_PERIOD))
 		&& !(SCpnt->flags & WAS_RESET))
 	    {
 		printk("scsi%d channel %d : resetting for second half of retries.\n",
@@ -617,7 +615,6 @@
 		scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS);
 		break;
 	    }
-
 	}
 	else
 	{
@@ -935,6 +932,12 @@
                 }
 
 		host->last_reset = jiffies;
+		host->resetting = 1;
+		/*
+		 * I suppose that the host reset callback will not play
+		 * with the resetting field. We have just set the resetting
+		 * flag here. -arca
+		 */
 		temp = host->hostt->reset(SCpnt, reset_flags);
 		/*
 		  This test allows the driver to introduce an additional bus
@@ -953,7 +956,13 @@
 	    {
 		if (!host->block) host->host_busy++;
 		host->last_reset = jiffies;
-	        SCpnt->flags |= (WAS_RESET | IS_RESETTING);
+		host->resetting = 1;
+		SCpnt->flags |= (WAS_RESET | IS_RESETTING);
+		/*
+		 * I suppose that the host reset callback will not play
+		 * with the resetting field. We have just set the resetting
+		 * flag here. -arca
+		 */
 		temp = host->hostt->reset(SCpnt, reset_flags);
 		if (time_before(host->last_reset, jiffies) ||
 		    (time_after(host->last_reset, jiffies + 20 * HZ)))
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.1.131/linux/drivers/sound/Config.in	Fri Oct 23 22:01:21 1998
+++ linux/drivers/sound/Config.in	Thu Dec 17 09:04:49 1998
@@ -15,6 +15,12 @@
      bool 'Joystick support at boot time' CONFIG_SOUND_ES1370_JOYPORT_BOOT
   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
+     if [ "$CONFIG_SOUND_ES1371_JOYPORT_BOOT" = "y" ]; then
+        hex 'Gameport I/O 200,208,210,218' CONFIG_SOUND_ES1371_GAMEPORT 200
+     fi
+  fi
   dep_tristate 'S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
 fi
 
@@ -195,13 +201,14 @@
       int 'CS4232 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_CS4232_MPU_IRQ 9
   fi
 
-  dep_tristate 'Support for Yamaha OPL3-SA[2,3,x] based (PnP) cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
+  dep_tristate 'Support for Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_OPL3SA2" = "y" ]; then
-      hex 'OPL3SA2 audio I/O base 530, 604, E80 or F40' CONFIG_OPL3SA2_BASE 530
-      int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 11
+      hex 'OPL3SA2 audio I/O base (530 - F48 valid)' CONFIG_OPL3SA2_BASE 530
+      int 'OPL3SA2 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_IRQ 9
       int 'OPL3SA2 audio DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA 0
       int 'OPL3SA2 second (duplex) DMA 0, 1 or 3' CONFIG_OPL3SA2_DMA2 1
-      hex 'OPL3SA2 MIDI I/O base 330, 370, 3B0 or 3F0' CONFIG_OPL3SA2_MPU_BASE 330
+      hex 'OPL3SA2 control I/O base (100 - FFE valid)' CONFIG_OPL3SA2_CTRL_BASE 370
+      hex 'OPL3SA2 MIDI I/O base (300 - 334 valid)' CONFIG_OPL3SA2_MPU_BASE 330
       int 'OPL3SA2 MIDI IRQ 5, 7, 9, 11, 12 or 15' CONFIG_OPL3SA2_MPU_IRQ 9
   fi
 
@@ -224,6 +231,17 @@
       int 'SGALAXY second (duplex) DMA 0, 1 or 3' CONFIG_SGALAXY_DMA2 3
       hex 'SGALAXY SB I/O base 220 or 240' CONFIG_SGALAXY_SGBASE 220
   fi
+
+  if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+    dep_tristate 'Support for AD1816(A) based cards (EXPERIMENTAL)' CONFIG_SOUND_AD1816 $CONFIG_SOUND
+    if [ "$CONFIG_SOUND_AD1816" = "y" ]; then
+      hex 'AD1816 audio I/O base 530, 604, E80 or F40' CONFIG_AD1816_BASE 530
+      int 'AD1816 audio IRQ 5, 7, 9, 11, 12 or 15' CONFIG_AD1816_IRQ 7
+      int 'AD1816 audio DMA 0, 1 or 3' CONFIG_AD1816_DMA 0
+      int 'AD1816 second (duplex) DMA 0, 1 or 3' CONFIG_AD1816_DMA2 3
+      int 'AD1816 clock chip frequency' CONFIG_AD1816_CLOCK 33000
+    fi
+  fi
   
   dep_tristate 'Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
   if [ "$CONFIG_SOUND_OPL3SA1" = "y" ]; then
@@ -252,7 +270,14 @@
   fi
   
   if [ "$CONFIG_ARM" = "y" ]; then
-      bool 'VIDC 16-bit sound' CONFIG_VIDC_SOUND
+    dep_tristate 'VIDC 16-bit sound' CONFIG_SOUND_VIDC $CONFIG_SOUND_OSS
+    dep_tristate 'Netwinder WaveArtist' CONFIG_SOUND_WAVEARTIST $CONFIG_SOUND_OSS
+    if [ "$CONFIG_SOUND_WAVEARTIST" != "n" ]; then
+      hex '  WaveArtist I/O base' CONFIG_WAVEARTIST_BASE 250
+      int '  WaveArtist IRQ' CONFIG_WAVEARTIST_IRQ 28
+      int '  WaveArtist DMA' CONFIG_WAVEARTIST_DMA 3
+      int '  WaveArtist second DMA' CONFIG_WAVEARTIST_DMA2 7
+    fi
   fi
   
   
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.1.131/linux/drivers/sound/Makefile	Thu Nov 19 09:56:28 1998
+++ linux/drivers/sound/Makefile	Wed Dec 16 12:52:00 1998
@@ -25,7 +25,7 @@
 export-objs	:=  ad1848.o audio_syms.o midi_syms.o mpu401.o \
 		    msnd.o opl3.o sb_card.o sequencer_syms.o \
 		    sound_core.o sound_firmware.o sound_syms.o \
-		    uart401.o
+		    uart401.o ad1816.o
 
 
 
@@ -66,13 +66,16 @@
 obj-$(CONFIG_SOUND_SB)		+= sb.o uart401.o
 obj-$(CONFIG_SOUND_SOFTOSS)	+= softoss2.o
 obj-$(CONFIG_SOUND_SGALAXY)	+= sgalaxy.o
+obj-$(CONFIG_SOUND_AD1816)      += ad1816.o
 obj-$(CONFIG_SOUND_SSCAPE)	+= sscape.o ad1848.o mpu401.o
 obj-$(CONFIG_SOUND_TRIX)	+= trix.o ad1848.o sb.o uart401.o
 obj-$(CONFIG_SOUND_UART6850)	+= uart6850.o
 obj-$(CONFIG_SOUND_VMIDI)	+= v_midi.o
 obj-$(CONFIG_SOUND_YM3812)	+= adlib_card.o opl3.o
-obj-$(CONFIG_VIDC_SOUND)	+= vidc_mod.o
+obj-$(CONFIG_SOUND_VIDC)	+= vidc_mod.o
+obj-$(CONFIG_SOUND_WAVEARTIST)	+= waveartist.o
 obj-$(CONFIG_SOUND_WAVEFRONT)   += wavefront.o
+
 #jnx
 obj-$(CONFIG_SOUND_ES1370)	+= es1370.o
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.1.131/linux/drivers/sound/ad1816.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/ad1816.c	Wed Dec 16 12:52:00 1998
@@ -0,0 +1,1400 @@
+/*
+
+AD1816 lowlevel sound driver for Linux 2.1.128 (and above)
+
+Copyright (C) 1998 by Thorsten Knabe <tek@rbg.informatik.tu-darmstadt.de>
+Based on the CS4232/AD1848 driver Copyright (C) by Hannu Savolainen 1993-1996
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+-------------------------------------------------------------------------------
+NOTE!   NOTE!   NOTE!   NOTE!   NOTE!   NOTE!   NOTE!   NOTE!   NOTE!
+
+This software is still under development. New versions of the driver 
+are available from:
+  http://www.student.informatik.tu-darmstadt.de/~tek/projects/linux.html
+or
+  http://www.tu-darmstadt.de/~tek01/projects/linux.html
+
+Please report any bugs to: tek@rbg.informatik.tu-darmstadt.de
+
+-------------------------------------------------------------------------------
+
+version: 1.1
+cvs: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.24.2.8 1998/12/04 16:39:46 tek Exp $
+status: experimental
+date: 1998/12/04
+
+Changes:
+	Oleg Drokin: Some cleanup of load/unload functions.    1998/11/24
+	
+	Thorsten Knabe: attach and unload rewritten, 
+	some argument checks added                             1998/11/30
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include "soundmodule.h"
+#include "sound_config.h"
+
+#ifdef CONFIG_AD1816
+
+#define DEBUGNOISE(x)
+#define DEBUGINFO(x) 
+#define DEBUGLOG(x) x
+#define DEBUGWARN(x) x
+
+#define CHECK_FOR_POWER { int timeout=100; \
+  while (timeout > 0 && (inb(devc->base)&0x80)!= 0x80) {\
+          timeout--; \
+  } \
+  if (timeout==0) {\
+          printk("ad1816: Check for power failed in %s line: %d\n",__FILE__,__LINE__); \
+  } \
+}
+
+/* structure to hold device specific information */
+typedef struct
+{
+        int            base;          /* set in attach */
+	int            irq;
+	int            dma_playback;
+        int            dma_capture;
+  
+        int            speed;         /* open */
+	int            channels;
+	int            audio_format;
+	unsigned char  format_bits;
+        int            audio_mode; 
+	int            opened;
+  
+        int            recmask;        /* setup */
+	int            supported_devices;
+	int            supported_rec_devices;
+	unsigned short levels[SOUND_MIXER_NRDEVICES];
+        int            dev_no;   /* this is the # in audio_devs and NOT 
+				    in ad1816_info */
+	int            irq_ok;
+	int            *osp;
+  
+}
+
+ad1816_info;
+
+static int  nr_ad1816_devs = 0;
+
+static int  ad1816_clockfreq=33000;
+
+/* for backward mapping of irq to sound device */
+
+static volatile char irq2dev[17] = {-1, -1, -1, -1, -1, -1, -1, -1,
+				    -1, -1, -1, -1, -1, -1, -1, -1, -1};
+
+
+/* supported audio formats */
+static int  ad_format_mask =
+AFMT_U8 | AFMT_S16_LE | AFMT_S16_BE | AFMT_MU_LAW | AFMT_A_LAW;
+
+/* array of device info structures */
+static ad1816_info dev_info[MAX_AUDIO_DEV];
+
+
+/* ------------------------------------------------------------------- */
+
+/* functions for easier access to inderect registers */
+
+static int ad_read (ad1816_info * devc, int reg)
+{
+	unsigned long   flags;
+	int result;
+	
+	CHECK_FOR_POWER;
+
+	save_flags (flags); /* make register access atomic */
+	cli ();
+	outb ((unsigned char) (reg & 0x3f), devc->base+0);
+	result = inb(devc->base+2);
+	result+= inb(devc->base+3)<<8;
+	restore_flags (flags);
+	
+	return (result);
+}
+
+
+static void ad_write (ad1816_info * devc, int reg, int data)
+{
+	unsigned long flags;
+	
+	CHECK_FOR_POWER;
+	
+	save_flags (flags); /* make register access atomic */
+	cli ();
+	outb ((unsigned char) (reg & 0xff), devc->base+0);
+	outb ((unsigned char) (data & 0xff),devc->base+2);
+	outb ((unsigned char) ((data>>8)&0xff),devc->base+3);
+	restore_flags (flags);
+
+}
+
+/* ------------------------------------------------------------------- */
+
+/* function interface required by struct audio_driver */
+
+static void ad1816_halt_input (int dev)
+{
+	unsigned long flags;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	unsigned char buffer;
+	
+	DEBUGINFO (printk("ad1816: halt_input called\n"));
+	
+	save_flags (flags); 
+	cli ();
+	
+	disable_dma(audio_devs[dev]->dmap_in->dma);
+	
+	buffer=inb(devc->base+9);
+	if (buffer & 0x01) {
+		/* disable capture */
+		outb(buffer & ~0x01,devc->base+9); 
+	}
+
+	enable_dma(audio_devs[dev]->dmap_in->dma);
+	
+	/* Clear interrupt status */
+	outb (~0x40, devc->base+1);	
+	
+	devc->audio_mode &= ~PCM_ENABLE_INPUT;
+	restore_flags (flags);
+}
+
+static void ad1816_halt_output (int dev)
+{
+	unsigned long  flags;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	
+	unsigned char buffer;
+
+	DEBUGINFO (printk("ad1816: halt_output called!\n"));
+
+	save_flags (flags); 
+	cli ();
+	/* Mute pcm output */
+	ad_write(devc, 4, ad_read(devc,4)|0x8080);
+
+	disable_dma(audio_devs[dev]->dmap_out->dma);
+	
+	buffer=inb(devc->base+8);
+	if (buffer & 0x01) {
+		/* disable capture */
+		outb(buffer & ~0x01,devc->base+8); 
+	}
+	enable_dma(audio_devs[dev]->dmap_out->dma);
+	
+	/* Clear interrupt status */
+	outb ((unsigned char)~0x80, devc->base+1);	
+
+	devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
+	restore_flags (flags);
+}
+
+static void ad1816_output_block (int dev, unsigned long buf, 
+				 int count, int intrflag)
+{
+	unsigned long flags;
+	unsigned long cnt;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	
+	DEBUGINFO(printk("ad1816: output_block called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
+  
+	cnt = count/4 - 1;
+  
+	save_flags (flags);
+	cli ();
+	
+	/* set transfer count */
+	ad_write (devc, 8, cnt & 0xffff); 
+	
+	devc->audio_mode |= PCM_ENABLE_OUTPUT; 
+	restore_flags (flags);
+}
+
+
+static void ad1816_start_input (int dev, unsigned long buf, int count,
+				int intrflag)
+{
+	unsigned long flags;
+	unsigned long  cnt;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	
+	DEBUGINFO(printk("ad1816: start_input called buf=%ld count=%d flags=%d\n",buf,count,intrflag));
+
+	cnt = count/4 - 1;
+
+	save_flags (flags); /* make register access atomic */
+	cli ();
+
+	/* set transfer count */
+	ad_write (devc, 10, cnt & 0xffff); 
+
+	devc->audio_mode |= PCM_ENABLE_INPUT;
+	restore_flags (flags);
+}
+
+
+static int ad1816_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+	return -(EINVAL);
+}
+
+
+static int ad1816_prepare_for_input (int dev, int bsize, int bcount)
+{
+	unsigned long flags;
+	unsigned int freq;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	unsigned char fmt_bits;
+	
+	DEBUGINFO (printk ("ad1816: prepare_for_input called: bsize=%d bcount=%d\n",bsize,bcount));
+
+	save_flags (flags); 
+	cli ();
+	
+	fmt_bits= (devc->format_bits&0x7)<<3;
+	
+	/* set mono/stereo mode */
+	if (devc->channels > 1) {
+		fmt_bits |=0x4;
+	}
+
+	/* set Mono/Stereo in playback/capture register */
+	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
+	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
+  
+	/* If compiled into kernel, AD1816_CLOCK is defined, so use it */
+#ifdef AD1816_CLOCK 
+	ad1816_clockfreq=AD1816_CLOCK;
+#endif
+
+	/* capture/playback frequency correction for soundcards 
+	   with clock chips != 33MHz (allowed range 5 - 100 kHz) */
+
+	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
+		ad1816_clockfreq=33000;
+	}
+	
+	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
+
+	/* write playback/capture speeds */
+	ad_write (devc, 2, freq & 0xffff);	
+	ad_write (devc, 3, freq & 0xffff);	
+
+	restore_flags (flags);
+
+	ad1816_halt_input(dev);
+	return 0;
+}
+
+static int ad1816_prepare_for_output (int dev, int bsize, int bcount)
+{
+	unsigned long flags;
+	unsigned int freq;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	unsigned char fmt_bits;
+
+	DEBUGINFO (printk ("ad1816: prepare_for_output called: bsize=%d bcount=%d\n",bsize,bcount));
+
+	save_flags (flags); /* make register access atomic */
+	cli ();
+
+	fmt_bits= (devc->format_bits&0x7)<<3;
+	/* set mono/stereo mode */
+	if (devc->channels > 1) {
+		fmt_bits |=0x4;
+	}
+
+	/* write format bits to playback/capture registers */
+	outb( (inb(devc->base+8) & ~0x3C)|fmt_bits, devc->base+8); 
+	outb( (inb(devc->base+9) & ~0x3C)|fmt_bits, devc->base+9);
+  
+#ifdef AD1816_CLOCK 
+	ad1816_clockfreq=AD1816_CLOCK;
+#endif
+
+	/* capture/playback frequency correction for soundcards 
+	   with clock chips != 33MHz (allowed range 5 - 100 kHz)*/
+
+	if (ad1816_clockfreq<5000 || ad1816_clockfreq>100000) {
+		ad1816_clockfreq=33000;
+	}
+  
+	freq=((unsigned int)devc->speed*33000)/ad1816_clockfreq; 
+	
+	/* write playback/capture speeds */
+	ad_write (devc, 2, freq & 0xffff);
+	ad_write (devc, 3, freq & 0xffff);
+
+	restore_flags (flags);
+	
+	ad1816_halt_output(dev);
+	return 0;
+
+}
+
+static void ad1816_trigger (int dev, int state) 
+{
+	unsigned long flags;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+	DEBUGINFO (printk("ad1816: trigger called! (devc=%d,devc->base=%d\n",devc,devc->base));
+
+	/* mode may have changed */
+
+	save_flags (flags); /* make register access atomic */
+	cli ();
+
+	/* mask out modes not specified on open call */
+	state &= devc->audio_mode; 
+				
+	/* setup soundchip to new io-mode */
+	if (state & PCM_ENABLE_INPUT) {
+		/* enable capture */
+		outb(inb(devc->base+9)|0x01, devc->base+9);
+	} else {
+		/* disable capture */
+		outb(inb(devc->base+9)&~0x01, devc->base+9);
+	}
+
+	if (state & PCM_ENABLE_OUTPUT) {
+		/* enable playback */
+		outb(inb(devc->base+8)|0x01, devc->base+8);
+		/* unmute pcm output */
+		ad_write(devc, 4, ad_read(devc,4)&~0x8080);
+	} else {
+		/* mute pcm output */
+		ad_write(devc, 4, ad_read(devc,4)|0x8080);
+		/* disable capture */
+		outb(inb(devc->base+8)&~0x01, devc->base+8);
+	}
+	restore_flags (flags);
+}
+
+
+/* halt input & output */
+static void ad1816_halt (int dev)
+{
+	ad1816_halt_input(dev);
+	ad1816_halt_output(dev);
+}
+
+static void ad1816_reset (int dev)
+{
+	ad1816_halt (dev);
+}
+
+/* set playback speed */
+static int ad1816_set_speed (int dev, int arg)
+{
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	
+	if (arg == 0) {
+		return devc->speed;
+	}
+	/* range checking */
+	if (arg < 4000) {
+		arg = 4000;
+	}
+	if (arg > 55000) {
+		arg = 55000;
+	}
+
+	devc->speed = arg;
+	return devc->speed;
+
+}
+
+static unsigned int ad1816_set_bits (int dev, unsigned int arg)
+{
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+	
+	static struct format_tbl
+	{
+		int             format;
+		unsigned char   bits;
+	}
+	format2bits[] =
+	{
+		{
+			0, 0
+		}
+		,
+		{
+			AFMT_MU_LAW, 1
+		}
+		,
+		{
+			AFMT_A_LAW, 3
+		}
+		,
+		{
+			AFMT_IMA_ADPCM, 0
+		}
+		,
+		{
+			AFMT_U8, 0
+		}
+		,
+		{
+			AFMT_S16_LE, 2
+		}
+		,
+		{
+			AFMT_S16_BE, 6
+		}
+		,
+		{
+			AFMT_S8, 0
+		}
+		,
+		{
+			AFMT_U16_LE, 0
+		}
+		,
+		{
+			AFMT_U16_BE, 0
+		}
+  };
+	int  i, n = sizeof (format2bits) / sizeof (struct format_tbl);
+
+	/* return current format */
+	if (arg == 0) {     
+		return devc->audio_format;
+	}
+	
+	devc->audio_format = arg;
+
+	/* search matching format bits */
+	for (i = 0; i < n; i++) {
+		if (format2bits[i].format == arg) {
+			devc->format_bits = format2bits[i].bits;
+			devc->audio_format = arg;
+			return arg;
+		}
+	}
+	/* Still hanging here. Something must be terribly wrong */
+	devc->format_bits = 0;
+	return devc->audio_format = AFMT_U8;
+}
+
+static short ad1816_set_channels (int dev, short arg)
+{
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+	if (arg != 1 && arg != 2) {
+		return devc->channels;
+	}
+
+	devc->channels = arg;
+	return arg;
+}
+
+/* open device */
+static int ad1816_open (int dev, int mode) 
+{
+	ad1816_info    *devc = NULL;
+	unsigned long   flags;
+
+	/* is device number valid ? */
+	if (dev < 0 || dev >= num_audiodevs) { 
+		return -(ENXIO);
+	}
+
+	/* get device info of this dev */
+	devc = (ad1816_info *) audio_devs[dev]->devc; 
+
+	/* make check if device already open atomic */
+	save_flags (flags); 
+	cli ();
+
+	if (devc->opened) {
+		restore_flags (flags);
+		return -(EBUSY);
+	}
+
+	/* mark device as open */
+	devc->opened = 1; 
+
+	devc->audio_mode = 0;
+	devc->speed = 8000;
+	devc->audio_format=AFMT_U8;
+	devc->channels=1;
+
+	ad1816_reset(devc->dev_no); /* halt all pending output */
+	restore_flags (flags);
+	return 0;
+}
+
+static void ad1816_close (int dev) /* close device */
+{
+	unsigned long flags;
+	ad1816_info    *devc = (ad1816_info *) audio_devs[dev]->devc;
+
+	save_flags (flags); 
+	cli ();
+
+	/* halt all pending output */
+	ad1816_reset(devc->dev_no); 
+	
+	devc->opened = 0;
+	devc->audio_mode = 0;
+	devc->speed = 8000;
+	devc->audio_format=AFMT_U8;
+	devc->format_bits = 0;
+
+
+	restore_flags (flags);
+}
+
+
+/* ------------------------------------------------------------------- */
+
+/* Audio driver structure */
+
+static struct audio_driver ad1816_audio_driver =
+{
+	ad1816_open,
+	ad1816_close,
+	ad1816_output_block,
+	ad1816_start_input,
+	ad1816_ioctl,
+	ad1816_prepare_for_input,
+	ad1816_prepare_for_output,
+	ad1816_halt,
+	NULL,
+	NULL,
+	ad1816_halt_input,
+	ad1816_halt_output,
+	ad1816_trigger,
+	ad1816_set_speed,
+	ad1816_set_bits,
+	ad1816_set_channels,
+	NULL,
+	NULL
+};
+
+
+/* ------------------------------------------------------------------- */
+
+/* Interrupt handler */
+
+void ad1816_interrupt (int irq, void *dev_id, struct pt_regs *dummy)
+{
+	unsigned char   status;
+	ad1816_info    *devc;
+	int             dev;
+	unsigned long flags;
+
+	
+	if (irq < 0 || irq > 15) {
+	        printk ("ad1816: Got bogus interrupt %d\n", irq);
+		return;
+	}
+
+	dev = irq2dev[irq];
+	
+	if (dev < 0 || dev >= num_audiodevs) {
+	        printk ("ad1816: IRQ2AD1816-mapping failed for irq %d device %d\n", irq,dev);
+		return;	        
+	}
+
+	devc = (ad1816_info *) audio_devs[dev]->devc;
+	
+	save_flags(flags);
+	cli();
+
+	/* read interrupt register */
+	status = inb (devc->base+1); 
+	/* Clear all interrupt  */
+	outb (~status, devc->base+1);	
+
+	DEBUGNOISE (printk("ad1816: Got interrupt subclass %d\n",status));
+	
+	devc->irq_ok=1;
+
+	if (status == 0) {
+		DEBUGWARN(printk ("ad1816: interrupt: Got interrupt, but no reason?\n"));
+	}
+	if (devc->opened && (devc->audio_mode & PCM_ENABLE_INPUT) 
+	    && (status&64)){
+		DMAbuf_inputintr (dev);
+	}
+
+	if (devc->opened && (devc->audio_mode & PCM_ENABLE_OUTPUT) &&
+	    (status & 128)) {
+		DMAbuf_outputintr (dev, 1);
+	}
+	restore_flags(flags);
+}
+
+/* ------------------------------------------------------------------- */
+
+/* Mixer stuff */
+
+struct mixer_def {
+	unsigned int regno: 7;
+	unsigned int polarity:1;	/* 0=normal, 1=reversed */
+	unsigned int bitpos:4;
+	unsigned int nbits:4;
+};
+
+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,
+	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,
+	91,91,92,92,93,93,94,94,95,95,96,96,96,97,97,98,98,98,99,99,
+	100
+};
+
+typedef struct mixer_def mixer_ent;
+
+/*
+ * Most of the mixer entries work in backwards. Setting the polarity field
+ * makes them to work correctly.
+ *
+ * The channel numbering used by individual soundcards is not fixed. Some
+ * cards have assigned different meanings for the AUX1, AUX2 and LINE inputs.
+ * The current version doesn't try to compensate this.
+ */
+
+#define MIX_ENT(name, reg_l, pola_l, pos_l, len_l, reg_r, pola_r, pos_r, len_r)	\
+  {{reg_l, pola_l, pos_l, len_l}, {reg_r, pola_r, pos_r, len_r}}
+
+
+mixer_ent mix_devices[SOUND_MIXER_NRDEVICES][2] = {
+MIX_ENT(SOUND_MIXER_VOLUME,	14, 1, 8, 5,	14, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_BASS,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_TREBLE,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_SYNTH,	 5, 1, 8, 6,	 5, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_PCM,	 4, 1, 8, 6,	 4, 1, 0, 6),
+MIX_ENT(SOUND_MIXER_SPEAKER,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE,	18, 1, 8, 5,	18, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_MIC,	19, 1, 8, 5,	19, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_CD,	 	15, 1, 8, 5,	15, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_IMIX,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_ALTPCM,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_RECLEV,	20, 0, 8, 4,	20, 0, 0, 4),
+MIX_ENT(SOUND_MIXER_IGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_OGAIN,	 0, 0, 0, 0,	 0, 0, 0, 0),
+MIX_ENT(SOUND_MIXER_LINE1, 	17, 1, 8, 5,	17, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE2,	16, 1, 8, 5,	16, 1, 0, 5),
+MIX_ENT(SOUND_MIXER_LINE3,      39, 0, 9, 4,    39, 1, 0, 5)
+};
+
+
+static unsigned short default_mixer_levels[SOUND_MIXER_NRDEVICES] =
+{
+	0x6464,			/* Master Volume */
+	0x3232,			/* Bass */
+	0x3232,			/* Treble */
+	0x0000,			/* FM */
+	0x6464,			/* PCM */
+	0x0000,			/* PC Speaker */
+	0x0000,			/* Ext Line */
+	0x0000,			/* Mic */
+	0x0000,			/* CD */
+	0x0000,			/* Recording monitor */
+	0x0000,			/* SB PCM */
+	0x0000,			/* Recording level */
+	0x0000,			/* Input gain */
+	0x0000,			/* Output gain */
+	0x0000,			/* Line1 */
+	0x0000,			/* Line2 */
+	0x0000			/* Line3 (usually line in)*/
+};
+
+#define LEFT_CHN	0
+#define RIGHT_CHN	1
+
+
+
+static int
+ad1816_set_recmask (ad1816_info * devc, int mask)
+{
+	unsigned char   recdev;
+	int             i, n;
+	
+	mask &= devc->supported_rec_devices;
+	
+	n = 0;
+	/* Count selected device bits */
+	for (i = 0; i < 32; i++) {
+		if (mask & (1 << i)) {
+			n++;
+		}
+	}
+	
+	if (n == 0) {
+		mask = SOUND_MASK_MIC;
+	} else if (n != 1) { /* Too many devices selected */
+		/* Filter out active settings */
+		mask &= ~devc->recmask;	
+		
+		n = 0;
+		/* Count selected device bits */
+		for (i = 0; i < 32; i++) {	
+			if (mask & (1 << i)) {
+				n++;
+			}
+		}
+		
+		if (n != 1) {
+			mask = SOUND_MASK_MIC;
+		}
+	}
+	
+	switch (mask) {
+	case SOUND_MASK_MIC:
+		recdev = 5;
+		break;
+		
+	case SOUND_MASK_LINE:
+		recdev = 0;
+		break;
+		
+	case SOUND_MASK_CD:
+		recdev = 2;
+		break;
+		
+	case SOUND_MASK_LINE1:
+		recdev = 4;
+		break;
+		
+	case SOUND_MASK_LINE2:
+		recdev = 3;
+		break;
+		
+	case SOUND_MASK_VOLUME:
+		recdev = 1;
+		break;
+		
+	default:
+		mask = SOUND_MASK_MIC;
+		recdev = 5;
+	}
+	
+	recdev <<= 4;
+	ad_write (devc, 20, 
+		  (ad_read (devc, 20) & 0x8f8f) | recdev | (recdev<<8));
+
+	devc->recmask = mask;
+	return mask;
+}
+
+static void
+change_bits (int *regval, int dev, int chn, int newval)
+{
+	unsigned char   mask;
+	int             shift;
+  
+	/* Reverse polarity*/
+
+	if (mix_devices[dev][chn].polarity == 1) {	
+		newval = 100 - newval;
+	}
+
+	mask = (1 << mix_devices[dev][chn].nbits) - 1;
+	shift = mix_devices[dev][chn].bitpos;
+	/* Scale it */
+	newval = (int) ((newval * mask) + 50) / 100;	
+	/* Clear bits */
+	*regval &= ~(mask << shift);	
+	/* Set new value */
+	*regval |= (newval & mask) << shift;	
+}
+
+static int
+ad1816_mixer_get (ad1816_info * devc, int dev)
+{
+	DEBUGINFO(printk("ad1816: mixer_get called!\n"));
+	
+	/* range check + supported mixer check */
+	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES ) {
+	        return (-(EINVAL));
+	}
+	if (!((1 << dev) & devc->supported_devices)) {
+		return -(EINVAL);
+	}
+	
+	return devc->levels[dev];
+}
+
+static int
+ad1816_mixer_set (ad1816_info * devc, int dev, int value)
+{
+	int   left = value & 0x000000ff;
+	int   right = (value & 0x0000ff00) >> 8;
+	int   retvol;
+
+	int   regoffs;
+	int   val;
+	int   valmute;
+
+	DEBUGINFO(printk("ad1816: mixer_set called!\n"));
+	
+	if (dev < 0 || dev >= SOUND_MIXER_NRDEVICES ) {
+		return -(EINVAL);
+	}
+
+	if (left > 100) {
+		left = 100;
+	}
+	if (left < 0) {
+		left = 0;
+	}
+	if (right > 100) {
+		right = 100;
+	}
+	if (right < 0) {
+		right = 0;
+	}
+	
+	/* Mono control */
+	if (mix_devices[dev][RIGHT_CHN].nbits == 0) {	
+		right = left;
+	}
+	retvol = left | (right << 8);
+	
+	/* Scale it */
+	
+	left = mix_cvt[left];
+	right = mix_cvt[right];
+
+	/* reject all mixers that are not supported */
+	if (!(devc->supported_devices & (1 << dev))) {
+		return -(EINVAL);
+	}
+	
+	/* sanity check */
+	if (mix_devices[dev][LEFT_CHN].nbits == 0) {
+		return -(EINVAL);
+	}
+
+	/* keep precise volume internal */
+	devc->levels[dev] = retvol;
+
+	/* Set the left channel */
+	regoffs = mix_devices[dev][LEFT_CHN].regno;
+	val = ad_read (devc, regoffs);
+	change_bits (&val, dev, LEFT_CHN, left);
+
+	valmute=val;
+
+	/* Mute bit masking on some registers */
+	if ( regoffs==5 || regoffs==14 || regoffs==15 ||
+	     regoffs==16 || regoffs==17 || regoffs==18 || 
+	     regoffs==19 || regoffs==39) {
+		if (left==0) {
+			valmute |= 0x8000;
+		} else {
+			valmute &= ~0x8000;
+		}
+	}
+	ad_write (devc, regoffs, valmute); /* mute */
+
+	/*
+	 * Set the right channel
+	 */
+ 
+	/* Was just a mono channel */
+	if (mix_devices[dev][RIGHT_CHN].nbits == 0) {
+		return retvol;		
+	}
+	regoffs = mix_devices[dev][RIGHT_CHN].regno;
+	val = ad_read (devc, regoffs);
+	change_bits (&val, dev, RIGHT_CHN, right);
+
+	valmute=val;
+	if ( regoffs==5 || regoffs==14 || regoffs==15 ||
+	     regoffs==16 || regoffs==17 || regoffs==18 || 
+	     regoffs==19 || regoffs==39) {
+		if (right==0) {
+			valmute |= 0x80;
+		} else {
+			valmute &= ~0x80;
+		}
+	}
+	ad_write (devc, regoffs, valmute); /* mute */
+	
+       	return retvol;
+}
+
+#define MIXER_DEVICES ( SOUND_MASK_VOLUME | \
+			SOUND_MASK_SYNTH | \
+			SOUND_MASK_PCM | \
+			SOUND_MASK_LINE | \
+			SOUND_MASK_LINE1 | \
+			SOUND_MASK_LINE2 | \
+			SOUND_MASK_LINE3 | \
+			SOUND_MASK_MIC | \
+			SOUND_MASK_CD | \
+			SOUND_MASK_RECLEV  \
+			)
+#define REC_DEVICES ( SOUND_MASK_LINE2 |\
+		      SOUND_MASK_LINE |\
+		      SOUND_MASK_LINE1 |\
+		      SOUND_MASK_MIC |\
+		      SOUND_MASK_CD |\
+		      SOUND_MASK_VOLUME \
+		      )
+     
+static void
+ad1816_mixer_reset (ad1816_info * devc)
+{
+	int  i;
+
+	devc->supported_devices = MIXER_DEVICES;
+	
+	devc->supported_rec_devices = REC_DEVICES;
+
+	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+		if (devc->supported_devices & (1 << i)) {
+			ad1816_mixer_set (devc, i, default_mixer_levels[i]);
+		}
+	}
+	ad1816_set_recmask (devc, SOUND_MASK_MIC);
+}
+
+static int
+ad1816_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+	ad1816_info    *devc = mixer_devs[dev]->devc;
+	int val;
+  
+	DEBUGINFO(printk("ad1816: mixer_ioctl called!\n"));
+  
+	/* Mixer ioctl */
+	if (((cmd >> 8) & 0xff) == 'M') { 
+		
+		/* set ioctl */
+		if (_IOC_DIR (cmd) & _IOC_WRITE) { 
+			switch (cmd & 0xff){
+			case SOUND_MIXER_RECSRC:
+				
+				if (get_user(val, (int *)arg)) {
+					return -EFAULT;
+				}
+				val=ad1816_set_recmask (devc, val);
+				        return put_user(val, (int *)arg);
+				break;
+				
+			default:
+				if (get_user(val, (int *)arg)){
+					return -EFAULT;
+				}
+				if ((val=ad1816_mixer_set (devc, cmd & 0xff, val))<0) {
+				        return val;
+				} else {
+				        return put_user(val, (int *)arg);
+				}
+			}
+		} else { 
+			/* read ioctl */
+			switch (cmd & 0xff) {
+				
+			case SOUND_MIXER_RECSRC:
+				val=devc->recmask;
+				return put_user(val, (int *)arg);
+				break;
+				
+			case SOUND_MIXER_DEVMASK:
+				val=devc->supported_devices;
+				return put_user(val, (int *)arg);
+				break;
+
+			case SOUND_MIXER_STEREODEVS:
+				val=devc->supported_devices & ~(SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
+				return put_user(val, (int *)arg);
+				break;
+				
+			case SOUND_MIXER_RECMASK:
+				val=devc->supported_rec_devices;
+				return put_user(val, (int *)arg);
+				break;
+				
+			case SOUND_MIXER_CAPS:
+				val=SOUND_CAP_EXCL_INPUT;
+				return put_user(val, (int *)arg);
+				break;
+				
+			default:
+			        if ((val=ad1816_mixer_get (devc, cmd & 0xff))<0) {
+				        return val;
+				} else {
+				        return put_user(val, (int *)arg);
+				}
+			}
+		}
+	} else {
+		/* not for mixer */
+		return -(EINVAL);
+	}
+}
+
+/* ------------------------------------------------------------------- */
+
+/* Mixer structure */
+
+static struct mixer_operations ad1816_mixer_operations =
+{
+	"AD1816",
+	"AD1816 Mixer",
+	ad1816_mixer_ioctl
+};
+
+
+/* ------------------------------------------------------------------- */
+
+/* stuff for card recognition, init and unloading */
+
+
+/* replace with probe routine */
+int probe_ad1816 ( struct address_info *hw_config )
+{
+	ad1816_info    *devc = &dev_info[nr_ad1816_devs];
+	int io_base=hw_config->io_base;
+	int *osp=hw_config->osp;
+	int tmp;
+	
+	printk("ad1816: AD1816 sounddriver Copyright (C) 1998 by Thorsten Knabe\n");
+	printk("ad1816: $Header: /home/tek/tmp/CVSROOT/sound21/ad1816.c,v 1.24.2.8 1998/12/04 16:39:46 tek Exp $\n");
+
+	if (check_region (io_base, 16)) {
+		printk ("ad1816: I/O port 0x%03x not free\n", io_base);
+		return 0;
+	}
+
+	DEBUGLOG(printk ("ad1816: detect(%x)\n", io_base));
+	
+	if (nr_ad1816_devs >= MAX_AUDIO_DEV) {
+		printk ("ad1816: detect error - step 0\n");
+		return 0;
+	}
+  
+	devc->base = io_base;
+	devc->irq_ok = 0;
+	devc->irq = 0;
+	devc->opened = 0;
+	devc->osp = osp;
+
+	/* base+0: bit 1 must be set but not 255 */
+	tmp=inb(devc->base);
+	if ( (tmp&0x80)==0 || tmp==255 ) {
+		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 or chip is not active (Test 0)\n"));
+		return(0);
+	}
+
+
+	/* writes to ireg 8 are copied to ireg 9 */
+	ad_write(devc,8,12345); 
+	if (ad_read(devc,9)!=12345) {
+		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 1)\n"));
+		return(0);
+	}
+  
+	/* writes to ireg 8 are copied to ireg 9 */
+	ad_write(devc,8,54321); 
+	if (ad_read(devc,9)!=54321) {
+		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 2)\n"));
+		return(0);
+	}
+  
+	/* writes to ireg 10 are copied to ireg 11 */
+	ad_write(devc,10,54321); 
+	if (ad_read(devc,11)!=54321) {
+		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 3)\n"));
+		return(0);
+	}
+
+	/* writes to ireg 10 are copied to ireg 11 */
+	ad_write(devc,10,12345); 
+	if (ad_read(devc,11)!=12345) {
+		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 4)\n"));
+		return(0);
+	}
+	
+	/* bit in base +1 cannot be set to 1 */
+	tmp=inb(devc->base+1);
+	outb(0xff,devc->base+1); 
+	if (inb(devc->base+1)!=tmp) {
+		DEBUGLOG (printk ("ad1816: Chip is not an AD1816 (Test 5)\n"));
+		return(0);
+	}
+
+  
+	DEBUGLOG (printk ("ad1816: detect() - Detected OK\n"));
+	DEBUGLOG (printk ("ad1816: AD1816 Version: %d\n",ad_read(devc,45)));
+	
+	/*  detection was successful */
+	return 1; 
+}
+
+
+/* allocate resources from the kernel. If any allocation fails, free
+   all allocated resources and exit attach.
+  
+ */
+
+void attach_ad1816 (struct address_info *hw_config)
+{
+	int             my_dev;
+	char            dev_name[100];
+	ad1816_info    *devc = &dev_info[nr_ad1816_devs];
+	
+
+	/* allocate i/o ports */
+       	request_region (hw_config->io_base, 16, "AD1816 Sound");
+	devc->base = hw_config->io_base;	
+
+	/* disable all interrupts */
+	ad_write(devc,1,0);     
+
+	/* Clear pending interrupts */
+	outb (0, devc->base+1);	
+
+	/* allocate irq */
+	if (hw_config->irq < 0 || hw_config->irq > 15) {
+		release_region(hw_config->io_base, 16);
+		return;	  
+	}
+	if (request_irq(hw_config->irq, ad1816_interrupt,0,
+			"SoundPort",
+			hw_config->osp) < 0)	{
+	        printk ("ad1816: IRQ in use\n");
+		release_region(hw_config->io_base, 16);
+		return;
+	}
+	devc->irq=hw_config->irq;
+
+	/* DMA stuff */
+	if (sound_alloc_dma (hw_config->dma, "Sound System")) {
+		printk ("ad1816: Can't allocate DMA%d\n", hw_config->dma);
+		free_irq(hw_config->irq,hw_config->osp);
+		release_region(hw_config->io_base, 16);
+		return;
+	}
+	devc->dma_playback=hw_config->dma;
+	
+	if ( hw_config->dma2 != -1 && hw_config->dma2 != hw_config->dma) {
+		if (sound_alloc_dma (hw_config->dma2, "Sound System (capture)")) {
+			printk ("ad1816: Can't allocate DMA%d\n", hw_config->dma2);
+			sound_free_dma(hw_config->dma);
+			free_irq(hw_config->irq,hw_config->osp);
+			release_region(hw_config->io_base, 16);
+			return;
+		}
+		devc->dma_capture=hw_config->dma2;
+		devc->audio_mode=DMA_AUTOMODE|DMA_DUPLEX;
+	} else {
+	        devc->dma_capture=-1;
+		devc->audio_mode=DMA_AUTOMODE;
+	}
+
+	sprintf (dev_name,"AD1816 audio driver");
+  
+	conf_printf2 (dev_name,
+		      devc->base, devc->irq, hw_config->dma, hw_config->dma2);
+
+	/* register device */
+	if ((my_dev = sound_install_audiodrv (AUDIO_DRIVER_VERSION,
+					      dev_name,
+					      &ad1816_audio_driver,
+					      sizeof (struct audio_driver),
+					      devc->audio_mode,
+					      ad_format_mask,
+					      devc,
+					      hw_config->dma, 
+					      hw_config->dma2)) < 0) {
+		printk ("ad1816: Can't install sound driver\n");
+		if (devc->dma_capture>=0) {
+		        sound_free_dma(hw_config->dma2);
+		}
+		sound_free_dma(hw_config->dma);
+		free_irq(hw_config->irq,hw_config->osp);
+		release_region(hw_config->io_base, 16);
+		return;
+
+	}
+
+	/* fill rest of structure with reasonable default values */
+	irq2dev[hw_config->irq] = devc->dev_no = my_dev;
+	devc->opened = 0;
+	devc->irq_ok = 0;
+	devc->osp = hw_config->osp;  
+	nr_ad1816_devs++;
+
+	ad_write(devc,32,0x80f0); /* sound system mode */
+	ad_write(devc,33,0x03f8); /* enable all audiosources for dsp */
+	ad_write(devc,4,0x8080);  /* default values for volumes (muted)*/
+	ad_write(devc,5,0x8080);
+	ad_write(devc,6,0x8080);
+	ad_write(devc,7,0x8080);
+	ad_write(devc,15,0x8888);
+	ad_write(devc,16,0x8888);
+	ad_write(devc,17,0x8888);
+	ad_write(devc,18,0x8888);
+	ad_write(devc,19,0xc888); /* +20db mic active */
+	ad_write(devc,14,0x0000); /* Master volume unmuted full power */
+	ad_write(devc,39,0x009f); /* 3D effect on 0% phone out muted */
+	ad_write(devc,44,0x0080); /* everything on power, 3d enabled for d/a */
+	outb(0x10,devc->base+8); /* set dma mode */
+	outb(0x10,devc->base+9);
+  
+	/* enable capture + playback interrupt */
+	ad_write(devc,1,0xc000); 
+	
+	/* set mixer defaults */
+	ad1816_mixer_reset (devc); 
+  
+	/* register mixer */
+	if ((audio_devs[my_dev]->mixer_dev=sound_install_mixer(
+				       MIXER_DRIVER_VERSION,
+				       dev_name,
+				       &ad1816_mixer_operations,
+				       sizeof (struct mixer_operations),
+				       devc)) >= 0) {
+		audio_devs[my_dev]->min_fragment = 0;
+	}
+}
+
+void unload_card(ad1816_info *devc)
+{
+	int  mixer, dev = 0;
+	
+	if (devc != NULL) {
+		DEBUGLOG (printk("ad1816: Unloading card at base=%x\n",devc->base));
+		
+		dev = devc->dev_no;
+		mixer = audio_devs[dev]->mixer_dev;
+
+		/* unreg mixer*/
+		if(mixer>=0) {
+			sound_unload_mixerdev(mixer);
+		}
+		sound_unload_audiodev(dev);
+		
+		/* free dma channels */
+		if (devc->dma_capture>=0) {
+			sound_free_dma(devc->dma_capture);
+		}
+
+		/* card wont get added if resources could not be allocated
+		   thus we need not ckeck if allocation was successful */
+		sound_free_dma (devc->dma_playback);
+		free_irq(devc->irq, devc->osp);
+		release_region (devc->base, 16);
+		
+		DEBUGLOG (printk("ad1816: Unloading card at base=%x was successful\n",devc->base));
+		
+	} else {
+		printk ("ad1816: no device/card specified\n");
+	}
+}
+
+void unload_ad1816 (struct address_info *hw_config)
+{
+	int          i;
+	ad1816_info  *devc = NULL;
+  
+	/* remove any soundcard */
+	if (hw_config==NULL) {
+		for (i = 0;  i < nr_ad1816_devs; i++) {
+			devc = &dev_info[i];
+			unload_card(devc);
+		}     
+		nr_ad1816_devs=0;
+	} else { 
+		/* remove specified soundcard */
+		for (i = 0; i < nr_ad1816_devs; i++) {
+		        int j;
+			
+			if (dev_info[i].base == hw_config->io_base) {
+				devc = &dev_info[i];
+				unload_card(devc);
+				nr_ad1816_devs--;
+				for ( j=i; j < nr_ad1816_devs ; j++) {
+					dev_info[j] = dev_info[j+1];
+				}
+				i--;
+			}
+		}
+	}
+}
+
+
+/* ----------------------------- 2.1.xxx module stuff ----------------- */
+
+EXPORT_SYMBOL(ad1816_interrupt);
+EXPORT_SYMBOL(probe_ad1816);
+EXPORT_SYMBOL(attach_ad1816);
+EXPORT_SYMBOL(unload_ad1816);
+
+
+#ifdef MODULE
+
+int             io = -1;
+int             irq = -1;
+int             dma = -1;
+int             dma2 = -1;
+
+MODULE_PARM(io,"i");
+MODULE_PARM(irq,"i");
+MODULE_PARM(dma,"i");
+MODULE_PARM(dma2,"i");
+MODULE_PARM(ad1816_clockfreq,"i");
+
+struct address_info cfg;
+
+
+int init_module(void)
+{
+        if (io == -1 || irq == -1 || dma == -1 || dma2 == -1) {
+		printk("ad1816: dma, dma2, irq and io must be set.\n");
+                return -EINVAL;
+        }
+        cfg.io_base = io;
+        cfg.irq = irq;
+        cfg.dma = dma;
+        cfg.dma2 = dma2;
+	
+        if (probe_ad1816(&cfg) == 0) {
+                return -ENODEV;
+	}
+        attach_ad1816(&cfg);
+        SOUND_LOCK;
+        return 0;
+}
+
+
+void cleanup_module(void)
+{
+        unload_ad1816(NULL);
+        SOUND_LOCK_END;
+}
+
+#endif /* MODULE */
+
+#endif /* CONFIG_AD1816 */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.1.131/linux/drivers/sound/ad1848.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/sound/ad1848.c	Wed Dec 16 12:52:01 1998
@@ -442,10 +442,6 @@
 	left = mix_cvt[left];
 	right = mix_cvt[right];
 
-	/* Scale it again */
-	left = mix_cvt[left];
-	right = mix_cvt[right];
-
 	if (devc->mix_devices[dev][LEFT_CHN].nbits == 0)
 		return -EINVAL;
 
@@ -1205,15 +1201,17 @@
 
 	{
 		int             tmout;
-
-		disable_dma(audio_devs[dev]->dmap_in->dma);
+		
+		if(!isa_dma_bridge_buggy)
+		        disable_dma(audio_devs[dev]->dmap_in->dma);
 
 		for (tmout = 0; tmout < 100000; tmout++)
 			if (ad_read(devc, 11) & 0x10)
 				break;
 		ad_write(devc, 9, ad_read(devc, 9) & ~0x02);	/* Stop capture */
 
-		enable_dma(audio_devs[dev]->dmap_in->dma);
+		if(!isa_dma_bridge_buggy)
+		        enable_dma(audio_devs[dev]->dmap_in->dma);
 		devc->audio_mode &= ~PCM_ENABLE_INPUT;
 	}
 
@@ -1240,14 +1238,17 @@
 	{
 		int             tmout;
 
-		disable_dma(audio_devs[dev]->dmap_out->dma);
+		if(!isa_dma_bridge_buggy)
+		        disable_dma(audio_devs[dev]->dmap_out->dma);
 
 		for (tmout = 0; tmout < 100000; tmout++)
 			if (ad_read(devc, 11) & 0x10)
 				break;
 		ad_write(devc, 9, ad_read(devc, 9) & ~0x01);	/* Stop playback */
 
-		enable_dma(audio_devs[dev]->dmap_out->dma);
+		if(!isa_dma_bridge_buggy)
+		       enable_dma(audio_devs[dev]->dmap_out->dma);
+
 		devc->audio_mode &= ~PCM_ENABLE_OUTPUT;
 	}
 
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v2.1.131/linux/drivers/sound/audio.c	Thu Nov 12 16:21:22 1998
+++ linux/drivers/sound/audio.c	Wed Dec 16 12:52:01 1998
@@ -199,6 +199,9 @@
 
 	p = 0;
 	c = count;
+	
+	if(count < 0)
+		return -EINVAL;
 
 	if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
 		return -EPERM;
@@ -810,8 +813,10 @@
 			{
 				reorganize_buffers(dev, dmap_in, 1);
 				if ((err = audio_devs[dev]->d->prepare_for_input(dev,
-					     dmap_in->fragment_size, dmap_in->nbufs)) < 0)
+					     dmap_in->fragment_size, dmap_in->nbufs)) < 0) {
+					restore_flags(flags);
 					return -err;
+				}
 				dmap_in->dma_mode = DMODE_INPUT;
 				audio_devs[dev]->enable_bits = bits;
 				DMAbuf_activate_recording(dev, dmap_in);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/cs4232.c linux/drivers/sound/cs4232.c
--- v2.1.131/linux/drivers/sound/cs4232.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/cs4232.c	Wed Dec 16 12:52:01 1998
@@ -63,9 +63,7 @@
 #define CS_OUT3(a, b, c)	{CS_OUT(a);CS_OUT(b);CS_OUT(c);}
 
 static int mpu_base = 0, mpu_irq = 0;
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
 static int synth_base = 0, synth_irq = 0;
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
 static int mpu_detected = 0;
 
 int probe_cs4232_mpu(struct address_info *hw_config)
@@ -188,7 +186,7 @@
 		}
 #endif
 
-#if defined(CONFIG_SOUND_WAVEFRONT) || defined(CONFIG_SOUND_WAVEFRONT_MODULE)
+		if(synth_base != 0)
 		{
 		    CS_OUT2 (0x15, 0x04);	        /* logical device 4 (WaveFront) */
 		    CS_OUT3 (0x47, (synth_base >> 8) & 0xff,
@@ -196,7 +194,7 @@
 		    CS_OUT2 (0x22, synth_irq);     	/* IRQ */
 		    CS_OUT2 (0x33, 0x01);	        /* Activate logical dev 4 */
 		}
-#endif
+
 		/*
 		 * Finally activate the chip
 		 */
@@ -331,12 +329,10 @@
 MODULE_PARM(mpuio,"i");
 MODULE_PARM(mpuirq,"i");
 
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
 int             synthio = -1;
 int             synthirq = -1;
 MODULE_PARM(synthio,"i");
 MODULE_PARM(synthirq,"i");
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
 
 EXPORT_NO_SYMBOLS;
 
@@ -350,35 +346,29 @@
 
 int init_module(void)
 {
-
-#ifndef CONFIG_SOUND_WAVEFRONT_MODULE
-
 	if (io == -1 || irq == -1 || dma == -1 || dma2 == -1)
 	{
 		printk(KERN_ERR "cs4232: dma, dma2, irq and io must be set.\n");
 		return -EINVAL;
 	}
-#else 
-	if (synthio == -1 || synthirq == -1 ||
-	    io == -1 || irq == -1 || dma == -1 || dma2 == -1)
+#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
+	if(synthio == -1)
+		printk(KERN_WARNING "cs4232: set synthio and synthirq to use the wavefront facilities.\n");
+	else
 	{
-		printk(KERN_ERR "cs4232: synthio, synthirq, dma, dma2, "
-		       "irq and io must be set.\n");
-		return -EINVAL;
+		synth_base = synthio;
+		synth_irq =  synthirq;	
 	}
-
-#endif CONFIG_SOUND_WAVEFRONT_MODULE
+#else
+	if(synthio != -1)
+		printk(KERN_WARNING "cs4232: wavefront support not enabled in this driver.\n");
+#endif
 
 	cfg.io_base = io;
 	cfg.irq = irq;
 	cfg.dma = dma;
 	cfg.dma2 = dma2;
 
-#ifdef CONFIG_SOUND_WAVEFRONT_MODULE
-	synth_base = synthio;
-	synth_irq =  synthirq;
-#endif CONFIG_SOUND_WAVEFRONT_MODULE	
-
 	if (probe_cs4232(&cfg) == 0)
 		return -ENODEV;
 
@@ -386,15 +376,15 @@
 	mpu_cfg.irq = -1;
 
 	if (mpuio != -1 && mpuirq != -1) {
-	    mpu_cfg.io_base = mpuio;
-	    mpu_cfg.irq = mpuirq;
-	    probe_cs4232_mpu(&mpu_cfg); /* Bug always returns 0 not OK -- AC */
+		mpu_cfg.io_base = mpuio;
+		mpu_cfg.irq = mpuirq;
+		probe_cs4232_mpu(&mpu_cfg); /* Bug always returns 0 not OK -- AC */
 	}
 
 	attach_cs4232(&cfg);
 
 	if (mpuio != -1 && mpuirq != -1) {
-	    attach_cs4232_mpu(&mpu_cfg);
+		attach_cs4232_mpu(&mpu_cfg);
 	}
 
 	SOUND_LOCK;
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.1.131/linux/drivers/sound/dev_table.h	Thu Nov 12 16:21:22 1998
+++ linux/drivers/sound/dev_table.h	Wed Dec 16 12:52:01 1998
@@ -33,6 +33,7 @@
 #define SNDCARD_WAVEFRONT               41
 #define SNDCARD_OPL3SA2                 42
 #define SNDCARD_OPL3SA2_MPU             43
+#define SNDCARD_AD1816                  88
 
 void attach_opl3sa_wss (struct address_info *hw_config);
 int probe_opl3sa_wss (struct address_info *hw_config);
@@ -202,6 +203,7 @@
 	short (*set_channels)(int dev, short channels);
 	void (*postprocess_write)(int dev); 	/* Device spesific postprocessing for written data */
 	void (*preprocess_read)(int dev); 	/* Device spesific preprocessing for read data */
+	void (*mmap)(int dev);
 };
 
 struct audio_operations 
@@ -427,6 +429,11 @@
 	{"SGALAXY", 0, SNDCARD_SGALAXY,	"Sound Galaxy WSS",		attach_sgalaxy, probe_sgalaxy, unload_sgalaxy},
 #endif
 
+#ifdef CONFIG_SOUND_AD1816
+        {"AD1816", 0, SNDCARD_AD1816,   "AD1816",               attach_ad1816, 
+probe_ad1816, unload_ad1816},
+#endif
+
 #ifdef CONFIG_SOUND_YM3812
 	{"OPL3", 0, SNDCARD_ADLIB,	"OPL-2/OPL-3 FM",		attach_adlib_card, probe_adlib, unload_adlib},
 #endif
@@ -493,7 +500,7 @@
 #if defined(CONFIG_SOUND_VMIDI) && defined(CONFIG_MIDI)
 	{"VMIDI", 0, SNDCARD_VMIDI,"Loopback MIDI Device",      attach_v_midi, probe_v_midi, unload_v_midi},
 #endif
-#ifdef CONFIG_VIDC_SOUND
+#ifdef CONFIG_SOUND_VIDC
 	{"VIDC", 0, SNDCARD_VIDC, "ARM VIDC 16-bit D/A", attach_vidc, probe_vidc, unload_vidc },
 #endif
 	{NULL, 0, 0,		"*?*",			NULL, NULL, NULL}
@@ -668,7 +675,7 @@
 	{SNDCARD_VMIDI, {0, 0, 0, -1}, SND_DEFAULT_ENABLE},
 #endif
 
-#ifdef CONFIG_VIDC_SOUND
+#ifdef CONFIG_SOUND_VIDC
 	{ SNDCARD_VIDC, {0, 0, 0, 0}, SND_DEFAULT_ENABLE },
 #endif
 	{0, {0}, 0}
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/dmabuf.c linux/drivers/sound/dmabuf.c
--- v2.1.131/linux/drivers/sound/dmabuf.c	Thu Nov 12 16:21:22 1998
+++ linux/drivers/sound/dmabuf.c	Wed Dec 16 12:52:01 1998
@@ -474,7 +474,7 @@
 		adev->dmap_in->closing = 1;
 
 	if (adev->open_mode & OPEN_WRITE)
-		if (!(adev->dmap_in->mapping_flags & DMA_MAP_MAPPED))
+		if (!(adev->dmap_out->mapping_flags & DMA_MAP_MAPPED))
 			if (!signal_pending(current) && (adev->dmap_out->dma_mode == DMODE_OUTPUT))
 				DMAbuf_sync(dev);
 	if (adev->dmap_out->dma_mode == DMODE_OUTPUT)
@@ -630,7 +630,10 @@
 		
 		f=claim_dma_lock();
 		clear_dma_ff(chan);
-		disable_dma(dmap->dma);
+		
+		if(!isa_dma_bridge_buggy)
+			disable_dma(dmap->dma);
+		
 		pos = get_dma_residue(chan);
 		
 		pos = dmap->bytes_in_use - pos;
@@ -650,7 +653,10 @@
 			pos = 0;
 		if (pos >= dmap->bytes_in_use)
 			pos = 0;
-		enable_dma(dmap->dma);
+		
+		if(!isa_dma_bridge_buggy)
+			enable_dma(dmap->dma);
+			
 		release_dma_lock(f);
 	}
 	restore_flags(flags);
@@ -727,7 +733,7 @@
 	struct audio_operations *adev = audio_devs[dev];
 	int err = 0;
 	struct dma_buffparms *dmap = adev->dmap_out;
-	int timeout;
+	long timeout;
 	long timeout_value;
 
 	if (dontblock)
@@ -1016,10 +1022,13 @@
 		unsigned long f;
 		
 		f=claim_dma_lock();
-		disable_dma(dmap->dma);
+		
+		if(!isa_dma_bridge_buggy)
+			disable_dma(dmap->dma);
 		clear_dma_ff(chan);
 		pos = dmap->bytes_in_use - get_dma_residue(chan);
-		enable_dma(dmap->dma);
+		if(!isa_dma_bridge_buggy)
+			enable_dma(dmap->dma);
 		release_dma_lock(f);
 		
 		pos = pos / dmap->fragment_size;	/* Actual qhead */
@@ -1111,10 +1120,12 @@
 		unsigned long f;
 		
 		f=claim_dma_lock();
-		disable_dma(dmap->dma);
+		if(!isa_dma_bridge_buggy)
+			disable_dma(dmap->dma);
 		clear_dma_ff(chan);
 		pos = dmap->bytes_in_use - get_dma_residue(chan);
-		enable_dma(dmap->dma);
+		if(!isa_dma_bridge_buggy)
+			enable_dma(dmap->dma);
 		release_dma_lock(f);
 
 		pos = pos / dmap->fragment_size;	/* Actual qhead */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/dmasound.c linux/drivers/sound/dmasound.c
--- v2.1.131/linux/drivers/sound/dmasound.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/sound/dmasound.c	Thu Dec 17 09:04:49 1998
@@ -90,7 +90,7 @@
 #include <linux/sound.h>
 #include <linux/init.h>
 
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
 #include <asm/setup.h>
 #endif
 #include <asm/system.h>
@@ -686,9 +686,9 @@
 
 
 #ifdef CONFIG_ATARI
-static void *AtaAlloc(unsigned int size, int flags) __init;
-static void AtaFree(void *, unsigned int size) __init;
-static int AtaIrqInit(void) __init;
+static void *AtaAlloc(unsigned int size, int flags);
+static void AtaFree(void *, unsigned int size);
+static int AtaIrqInit(void);
 #ifdef MODULE
 static void AtaIrqCleanUp(void);
 #endif /* MODULE */
@@ -709,9 +709,9 @@
 #endif /* CONFIG_ATARI */
 
 #ifdef CONFIG_AMIGA
-static void *AmiAlloc(unsigned int size, int flags) __init;
-static void AmiFree(void *, unsigned int) __init;
-static int AmiIrqInit(void) __init;
+static void *AmiAlloc(unsigned int size, int flags);
+static void AmiFree(void *, unsigned int);
+static int AmiIrqInit(void);
 #ifdef MODULE
 static void AmiIrqCleanUp(void);
 #endif /* MODULE */
@@ -726,9 +726,9 @@
 #endif /* CONFIG_AMIGA */
 
 #ifdef CONFIG_PPC
-static void *PMacAlloc(unsigned int size, int flags) __init;
-static void PMacFree(void *ptr, unsigned int size) __init;
-static int PMacIrqInit(void) __init;
+static void *PMacAlloc(unsigned int size, int flags);
+static void PMacFree(void *ptr, unsigned int size);
+static int PMacIrqInit(void);
 #ifdef MODULE
 static void PMacIrqCleanup(void);
 #endif /* MODULE */
@@ -2223,7 +2223,7 @@
 	atari_stram_free( obj );
 }
 
-static int AtaIrqInit(void)
+static int __init AtaIrqInit(void)
 {
 	/* Set up timer A. Timer A
 	   will receive a signal upon end of playing from the sound
@@ -2720,7 +2720,7 @@
 	amiga_chip_free (obj);
 }
 
-static int AmiIrqInit(void)
+static int __init AmiIrqInit(void)
 {
 	/* turn off DMA for audio channels */
 	custom.dmacon = AMI_AUDIO_OFF;
@@ -2988,7 +2988,7 @@
 	kfree(ptr);
 }
 
-static int PMacIrqInit(void)
+static int __init PMacIrqInit(void)
 {
 	if (request_irq(awacs_irq, pmac_awacs_intr, 0, "AWACS", 0)
 	    || request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "AWACS out", 0))
@@ -3850,7 +3850,7 @@
 };
 
 
-__initfunc(static void mixer_init(void))
+static void __init mixer_init(void)
 {
 #ifndef MODULE
 	int mixer_unit;
@@ -3898,6 +3898,42 @@
  */
 
 
+static int sq_allocate_buffers(void)
+{
+	int i;
+
+	if (sound_buffers)
+		return 0;
+	sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
+	if (!sound_buffers)
+		return -ENOMEM;
+	for (i = 0; i < numBufs; i++) {
+		sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
+		if (!sound_buffers[i]) {
+			while (i--)
+				sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+			kfree (sound_buffers);
+			sound_buffers = 0;
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+
+static void sq_release_buffers(void)
+{
+	int i;
+
+	if (sound_buffers) {
+		for (i = 0; i < numBufs; i++)
+			sound.mach.dma_free (sound_buffers[i], bufSize << 10);
+		kfree (sound_buffers);
+		sound_buffers = 0;
+	}
+}
+
+
 static void sq_setup(int numBufs, int bufSize, char **buffers)
 {
 #ifdef CONFIG_PPC
@@ -3913,7 +3949,6 @@
 	sq.front = sq.count = 0;
 	sq.rear = -1;
 	sq.write_queue = sq.open_queue = sq.sync_queue = 0;
-	sq.busy = 0;
 	sq.syncing = 0;
 
 	sq.playing = 0;
@@ -4033,9 +4068,12 @@
 		}
 		rc = 0;
 	}
+	sq.busy = 1;
+	rc = sq_allocate_buffers();
+	if (rc)
+		goto err_out_nobusy;
 	sq_setup(numBufs, bufSize << 10, sound_buffers);
 	sq.open_mode = file->f_flags;
-	sq.busy = 1;
 #ifdef CONFIG_ATARI
 	sq.ignore_int = 1;
 #endif /* CONFIG_ATARI */
@@ -4049,6 +4087,9 @@
 		sound_set_format(AFMT_MU_LAW);
 	}
 	return 0;
+err_out_nobusy:
+	sq.busy = 0;
+	WAKE_UP(sq.open_queue);
 err_out:
 	MOD_DEC_USE_COUNT;
 	return rc;
@@ -4101,8 +4142,10 @@
 	sound.soft = sound.dsp;
 	sound.hard = sound.dsp;
 	sound_silence();
-	if (rc == 0)
+	if (rc == 0) {
+		sq_release_buffers();
 		MOD_DEC_USE_COUNT;
+	}
 	return rc;
 }
 
@@ -4212,7 +4255,7 @@
 };
 
 
-__initfunc(static void sq_init(void))
+static void __init sq_init(void)
 {
 #ifndef MODULE
 	int sq_unit;
@@ -4407,7 +4450,7 @@
 };
 
 
-__initfunc(static void state_init(void))
+static void __init state_init(void)
 {
 #ifndef MODULE
 	int state_unit;
@@ -4430,15 +4473,14 @@
 /*** Config & Setup **********************************************************/
 
 
-__initfunc(void dmasound_init(void))
+void __init dmasound_init(void)
 {
 	int has_sound = 0;
-	int i;
 #ifdef CONFIG_PPC
 	struct device_node *np;
 #endif
 
-#ifdef __mc68000__
+#if defined(__mc68000__) || defined(CONFIG_APUS)
 	switch (m68k_machtype) {
 #ifdef CONFIG_ATARI
 	case MACH_ATARI:
@@ -4466,7 +4508,7 @@
 		break;
 #endif /* CONFIG_AMIGA */
 	}
-#endif /* __mc68000__ */
+#endif /* __mc68000__||CONFIG_APUS */
 
 #ifdef CONFIG_PPC
 	awacs_subframe = 0;
@@ -4501,8 +4543,10 @@
 		awacs_rx_irq = np->intrs[2].line;
 		awacs_tx_cmd_space = kmalloc((numBufs + 4) * sizeof(struct dbdma_cmd),
 					     GFP_KERNEL);
-		if (awacs_tx_cmd_space == NULL)
-			goto out_of_memory;
+		if (awacs_tx_cmd_space == NULL) {
+			printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
+			return;
+		}
 		awacs_tx_cmds = (volatile struct dbdma_cmd *)
 			DBDMA_ALIGN(awacs_tx_cmd_space);
 		awacs_reg[0] = MASK_MUX_CD;
@@ -4543,24 +4587,6 @@
 		return;
 
 	/* Set up sound queue, /dev/audio and /dev/dsp. */
-	sound_buffers = kmalloc (numBufs * sizeof(char *), GFP_KERNEL);
-	if (!sound_buffers) {
-	out_of_memory:
-		printk("DMA sound driver: Not enough buffer memory, driver disabled!\n");
-		return;
-	}
-	for (i = 0; i < numBufs; i++) {
-		sound_buffers[i] = sound.mach.dma_alloc (bufSize << 10, GFP_KERNEL);
-		if (!sound_buffers[i]) {
-			while (i--)
-				sound.mach.dma_free (sound_buffers[i], bufSize << 10);
-			kfree (sound_buffers);
-			sound_buffers = 0;
-			goto out_of_memory;
-		}
-	}
-
-	sq_setup(numBufs, bufSize << 10, sound_buffers);
 
 	/* Set default settings. */
 	sq_init();
@@ -4588,7 +4614,7 @@
 
 #define MAXARGS		8	/* Should be sufficient for now */
 
-__initfunc(void dmasound_setup(char *str, int *ints))
+void __init dmasound_setup(char *str, int *ints)
 {
 	/* check the bootstrap parameter for "dmasound=" */
 
@@ -4628,18 +4654,12 @@
 
 void cleanup_module(void)
 {
-	int i;
-
 	if (irq_installed) {
 		sound_silence();
 		sound.mach.irqcleanup();
 	}
 
-	if (sound_buffers) {
-		for (i = 0; i < numBufs; i++)
-			sound.mach.dma_free(sound_buffers[i], bufSize << 10);
-		kfree(sound_buffers);
-	}
+	sq_release_buffers();
 
 	if (mixer_unit >= 0)
 		unregister_sound_mixer(mixer_unit);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.1.131/linux/drivers/sound/es1370.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/es1370.c	Thu Dec 17 09:04:49 1998
@@ -79,6 +79,7 @@
  *    31.08.98   0.13  Fix realplayer problems - dac.count issues
  *    08.10.98   0.14  Joystick support fixed
  *		       -- Oliver Neukum <c188@org.chemie.uni-muenchen.de>
+ *    10.12.98   0.15  Fix drain_dac trying to wait on not yet initialized DMA
  *
  * some important things missing in Ensoniq documentation:
  *
@@ -998,7 +999,7 @@
 	unsigned long flags;
 	int count, tmo;
 	
-	if (s->dma_dac1.mapped)
+	if (s->dma_dac1.mapped || !s->dma_dac1.ready)
 		return 0;
         current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1033,7 +1034,7 @@
 	unsigned long flags;
 	int count, tmo;
 
-	if (s->dma_dac2.mapped)
+	if (s->dma_dac2.mapped || !s->dma_dac2.ready)
 		return 0;
         current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac2.wait, &wait);
@@ -2276,7 +2277,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1370: version v0.13 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1370: version v0.15 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1370, pcidev))) {
 		if (pcidev->base_address[0] == 0 || 
@@ -2401,8 +2402,6 @@
 		synchronize_irq();
 		free_irq(s->irq, s);
 		release_region(s->io, ES1370_EXTENT);
-		if (s->ctrl & CTRL_JYSTK_EN)
-			release_region(0x200, JOY_EXTENT);
 		unregister_sound_dsp(s->dev_audio);
 		unregister_sound_mixer(s->dev_mixer);
 		unregister_sound_dsp(s->dev_dac);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.1.131/linux/drivers/sound/es1371.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/es1371.c	Thu Dec 17 09:04:49 1998
@@ -23,12 +23,10 @@
  *
  *
  * Module command line parameters:
- *   joystick if 1 enables the joystick interface on the card; but it still
- *            needs a separate joystick driver (presumably PC standard, although
- *            the chip doc doesn't say anything and it looks slightly fishy from
- *            the PCI standpoint...)
- *
- *
+ *   joystick must be set to the base I/O-Port to be used for
+ *   the gameport. Legal values are 0x200, 0x208, 0x210 and 0x218.         
+ *   The gameport is mirrored eight times.
+ *        
  *  Supported devices:
  *  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible
  *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
@@ -49,11 +47,15 @@
  *                     Now mixer behaviour can basically be selected between
  *                     "OSS documented" and "OSS actual" behaviour
  *    31.08.98   0.4   Fix realplayer problems - dac.count issues
+ *    27.10.98   0.5   Fix joystick support
+ *                     -- Oliver Neukum (c188@org.chemie.uni-muenchen.de)
+ *    10.12.98   0.6   Fix drain_dac trying to wait on not yet initialized DMA
  *
  */
 
 /*****************************************************************************/
       
+#include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
 #include <linux/string.h>
@@ -1443,7 +1445,7 @@
 	unsigned long flags;
 	int count, tmo;
 	
-	if (s->dma_dac1.mapped)
+	if (s->dma_dac1.mapped || !s->dma_dac1.ready)
 		return 0;
         current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac1.wait, &wait);
@@ -1478,7 +1480,7 @@
 	unsigned long flags;
 	int count, tmo;
 
-	if (s->dma_dac2.mapped)
+	if (s->dma_dac2.mapped || !s->dma_dac2.ready)
 		return 0;
         current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac2.wait, &wait);
@@ -2672,7 +2674,13 @@
 /* maximum number of devices */
 #define NR_DEVICE 5
 
+#if CONFIG_SOUND_ES1371_JOYPORT_BOOT
+static int joystick[NR_DEVICE] = { 
+CONFIG_SOUND_ES1371_GAMEPORT
+, 0, };
+#else
 static int joystick[NR_DEVICE] = { 0, };
+#endif
 
 /* --------------------------------------------------------------------- */
 
@@ -2708,7 +2716,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "es1371: version v0.4 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "es1371: version v0.6 time " __TIME__ " " __DATE__ "\n");
 	while (index < NR_DEVICE && 
 	       (pcidev = pci_find_device(PCI_VENDOR_ID_ENSONIQ, PCI_DEVICE_ID_ENSONIQ_ES1371, pcidev))) {
 		if (pcidev->base_address[0] == 0 || 
@@ -2758,7 +2766,6 @@
 				printk(KERN_ERR "es1371: joystick address 0x%x already in use\n", joystick[index]);
 			else {
 				s->ctrl |= CTRL_JYSTK_EN | (((joystick[index] >> 3) & CTRL_JOY_MASK) << CTRL_JOY_SHIFT);
-				request_region(joystick[index], JOY_EXTENT, "es1371");
 			}
 		}
 		s->sctrl = 0;
@@ -2880,8 +2887,6 @@
 		synchronize_irq();
 		free_irq(s->irq, s);
 		release_region(s->io, ES1371_EXTENT);
-		if (s->ctrl & CTRL_JYSTK_EN)
-			release_region(((((s->ctrl >> CTRL_JOY_SHIFT) & CTRL_JOY_MASK) << 3) | 0x200), JOY_EXTENT);
 		unregister_sound_dsp(s->dev_audio);
 		unregister_sound_mixer(s->dev_mixer);
 		unregister_sound_dsp(s->dev_dac);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/gus_wave.c linux/drivers/sound/gus_wave.c
--- v2.1.131/linux/drivers/sound/gus_wave.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/gus_wave.c	Wed Dec 16 12:52:01 1998
@@ -1173,7 +1173,6 @@
 		gus_voice_fade(voice);
 	}
 
-	restore_flags(flags);
 	return 0;
 }
 
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/legacy.h linux/drivers/sound/legacy.h
--- v2.1.131/linux/drivers/sound/legacy.h	Fri Oct 23 22:01:22 1998
+++ linux/drivers/sound/legacy.h	Wed Dec 16 12:52:01 1998
@@ -33,6 +33,7 @@
 #define CONFIG_SB
 #define CONFIG_SOFTOSS
 #define CONFIG_SSCAPE
+#define CONFIG_AD1816
 #define CONFIG_TRIX
 #define CONFIG_VMIDI
 #define CONFIG_YM3812
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/ChangeLog.awe linux/drivers/sound/lowlevel/ChangeLog.awe
--- v2.1.131/linux/drivers/sound/lowlevel/ChangeLog.awe	Sat Nov 29 10:33:20 1997
+++ linux/drivers/sound/lowlevel/ChangeLog.awe	Wed Dec 31 16:00:00 1969
@@ -1,206 +0,0 @@
-ver.0.4.2c
-	- Add a mode to enable drum channel toggle via bank number
-	  change.
-
-ver.0.4.2b
-	- Clear voice position after note on
-	- Change nrvoices according to the current playing mode
-
-ver.0.4.2a
-	- Fix a bug in pitch calculation with scale parameter
-	- Change default chorus & reverb modes
-
-ver.0.4.2
-	- Use indirect voice allocation mode; used as default mode
-	- Add preset mapping
-	- Free buffers when resetting samples
-	- Set default preset/bank/drumset as variable
-	- Fix a bug in exclusive note-off
-	- Add channel reset control macro
-	- Change modwheel sensitivity as variable
-	- Add lock option in open_patch
-	- Add channel priority mode macro, and disable it as default
-	- Add unset effect macro
-	- Add user defined chorus/reverb modes
-	- Do not initialize effect parameters when allocating voices
-	- Accept realtime filter-Q parameter change
-	- Check value range of set/add effects
-	- Change drum flags automatically when receiving bank #128
-
-ver.0.4.1	development versions
-
-ver.0.4.0c
-	- Fix kernel oops when setting AWE_FX_ATTEN
-
-ver.0.4.0b
-	- Do not kill_note in start_note when velocity is zero
-
-ver.0.4.0a
-	- Fix a bug in channel pressure effects
-
-ver.0.4.0
-	- Support dynamic buffer allocation
-	- Add functions to open/close/unload a patch
-	- Change from pointer to integer index in voice/sample lists
-	- Support for Linux/Alpha-AXP
-	- Fix for FreeBSD
-	- Add sostenuto control
-	- Add midi channel priority
-	- Fix a bug in all notes off control
-	- Use AWE_DEFAULT_MEMSIZE always if defined
-	- Fix a bug in awe_reset causes seg fault when no DRAM onboard
-	- Use awe_mem_start variable instead of constant
-
-ver.0.3.3c
-	- Fix IOCTL_TO_USER for OSS-3.8 (on Linux-2.1.25)
-	- Fix i/o macros for mixer controls
-
-ver.0.3.3b
-	- Fix version number in awe_version.h
-	- Fix a small bug in noteoff/relese all
-
-ver.0.3.3a
-	- Fix all notes/sounds off
-	- Add layer effect control
-	- Add misc mode controls; realtime pan, version number, etc.
-	- Move gus bank control in misc mode control
-	- Modify awe_operations for OSS3.8b5
-	- Fix installation script
-
-ver.0.3.3
-	- Add bass/treble control in Emu8000 chip
-	- Add mixer device
-	- Fix sustain on to value 127
-
-ver.0.3.2
-	- Refuse linux-2.0.0 at installation
-	- Move awe_voice.h to /usr/include/linux
-
-ver.0.3.1b (not released)
-	- Rewrite chorus/reverb mode change functions
-	- Rewrite awe_detect & awe_check_dram routines
-
-ver.0.3.1a
-	- Fix a bug to reset voice counter in awe_reset
-	- Fix voice balance on GUS mode
-	- Make symlink on /usr/include/asm in install script
-
-ver.0.3.1
-	- Remove zero size arrays from awe_voice.h
-	- Fix init_fm routine
-	- Remove all samples except primary samples in REMOVE_LAST_SAMPLES
-
-ver.0.3.0a
-	- Add AWE_NOTEOFF_ALL control
-	- Remove AWE_INIT_ATTEN control
-
-ver.0.3.0
-	- Fix decay time table
-	- Add exclusive sounds mode
-	- Add capability to get current status
-
-ver.0.2.99e
-	- Add #ifdef for all sounds/notes off controls.
-	- Fix bugs on searching the default drumset/preset.
-	- Fix usslite patch to modify the default Config.in.
-
-ver.0.2.99d
-	- Fix bugs of attack/hold parameters
-	- Fix attack & decay time table
-
-ver.0.2.99c
-	- Change volume control messages (main & expression volume)
-	  to accesspt normal MIDI parameters in channel mode.
-	- Use channel mode in SEQ2 controls.
-
-ver.0.2.99b
-	- #ifdef patch manager functions (for OSS-3.7)
-
-ver.0.2.99a
-	- Fix sustain bug
-
-ver.0.2.99 (0.3 beta)
-	- Support multiple instruments
-
-ver.0.2.0c
-	- Add copyright notice
-	- FreeBSD 2.2-ALPHA integration
-
-ver.0.2.0b
-	- Remove buffered reading appended in v0.2.0a
-	- Remove SMAxW register check on writing
-	- Support Linux 2.1.x kernel
-	- Rewrite installation script
-
-ver.0.2.0a
-	- Define SEQUENCER_C for tuning.h for FreeBSD system
-	- Improvement of sample loading speed
-	- Fix installation script
-	- Add PnP driver functions for ISA PnP driver support
-
-ver.0.2.0
-	- Includes FreeBSD port
-	- Can load GUS compatible patches
-	- Change values of hardware control parameters for compatibility
-	  with GUS driver
-	- Accept 8bit or unsigned wave data
-	- Accept no blank loop data
-	- Add sample mode flags in sample_info
-
-ver.0.1.6
-	- Add voice effects control
-	- Fix awe_voice.h for word alignment
-
-ver.0.1.5c
-	- Fix FM(OPL) playback problem
-
-ver.0.1.5b
-	- Fix pitch calculation for fixed midi key
-
-ver.0.1.5a
-	- Fix bugs in removing samples from linked list.
-
-ver.0.1.5
-	- Add checksum verification for sample uploading
-	  (not compatible from older sample_info structure)
-	- Fix sample offset pointers to (actual value - 1)
-	- Add sequencer command to initialize awe32
-
-ver.0.1.4c
-	- Fix card detection and memory check function to avoid system crash
-	  at booting
-
-ver.0.1.4b
-	- Add release sustain mode
-	- Initialize FM each time after loading samples
-
-ver.0.1.4a
-	- Fix AWE card detection code
-	- Correct FM initialize position 
-	- Add non-releasing mode on voice info
-
-ver.0.1.4
-	- Add AWE card and DRAM detection codes
-	- Add FM initialization code
-	- Modify volume control
-	- Remove linear volume mode
-	- Change memory management; not using malloc dynamically
-	- Add remove-samples command
-	- Use internal id implicitly at loading samples
-
-ver.0.1.3
-	- Fix a bug on patch uploading to RAM
-
-ver.0.1.2
-	- Divide to separated packages
-	- Fix disagreed macro conditions
-	- Fix unresolved function bugs
-	- Integrate VoxWare and USS-Lite driver source (awe_voice.c)
-	  and remove awe_card.c
-
-ver.0.1.1
-	- Fix wrong sample numbers in sbktext
-	- Fix txt2sfx bug
-	- Fix pan parameter calculation
-	- Append USS-Lite/Linux2.0 driver
-
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/README.awe linux/drivers/sound/lowlevel/README.awe
--- v2.1.131/linux/drivers/sound/lowlevel/README.awe	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/lowlevel/README.awe	Wed Dec 31 16:00:00 1969
@@ -1,205 +0,0 @@
-================================================================
-	AWE32 Sound Driver for Linux and FreeBSD
-		version 0.4.2c; Oct. 7, 1997
-================================================================
-
-* GENERAL NOTES
-
-This is a sound driver extension for the Sound Blaster AWE32 and other
-compatible cards (AWE32-PnP, SB32, SB32-PnP, AWE64, etc.) to enable
-the wave synth operations.  The driver is provided for both Linux
-1.2.x and 2.[01].x kernels, and also FreeBSD on Intel x86 and DEC
-Alpha systems.   See INSTALL.awe (or INSTALL.fbsd) document for
-installation of the driver package.
-
-This driver was written by Takashi Iwai (iwai@dragon.mm.t.u-tokyo.ac.jp)  
-who also maintains the code.  Please forward any questions, bug fixes
-and suggestions directly to Iwai (_NOT_ to Linus Torvalds or Hannu
-Savolainen).
-
-
-* NOTE TO LINUX USERS
-
-To enable this driver on linux-2.[01].x kernels, you need turn on both 
-"lowlevel drivers support" and "AWE32 synth support" options in sound
-menu when configure your linux kernel and modules.  For more details,
-see the installation document in the original driver package
-(awedrv-0.4.2.tar.gz) available at the web page:
-	http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
-
-If you're using PnP cards, the card must be initialized before loading
-the sound driver.  There're several options to do this:
-    - Initialize the card via ISA PnP tools, and load the sound module.
-    - Initialize the card on DOS, and load linux by loadlin.exe
-    - Use PnP driver (for Linux-2.x.x)
-See the FAQ list on the URL above.
-
-
-* USING THE DRIVER
-
-The GM and GS sounds include multiple instrument layers.
-The current version supports this type of sounds with a special
-extension, but it uses a non-standard way of sequencer calls.  Then,
-so far, only drvmidi and playmidi can play the multiple instruments
-and stereo sounds properly as MIDI sequencers.
-
-To load SoundFont files, sfxload utility is required.
-All AWE32 driver and utilities can be downloaded from:
-	http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/
-
-The sfxload is included in the package awesfx-0.4.2.tgz. Binary
-packages are available there, too.  See the instruction in each
-package for installation.
-
-Sfxload reads a SoundFont file and transfers it to the sound driver.
-Note that new sfxload no longer requires -i option.
-
-	% sfxload synthgm.sbk
-
-You can tune up the sound via some new options, -A, -a and -d.
-
-	% sfxload -A2 synthgm.sbk
-
-See the manual of sfxload for more details.
-
-Now you can hear midi musics by supported midi players (drvmidi or
-playmidi-2.5).
-
-	% drvmidi foo.mid
-
-If you have only 512kb on the sound card, I recommend to use dynamic
-sample loading via -L option of drvmidi.  2MB GM/GS soundfont file is
-available in most midi files.
-
-	% sfxload synthgm
-	% drvmidi -L 2mbgmgs foo.mid
-
-Enjoy.
-
-
-* COMPILE FLAGS
-
-Compile conditions are defined in awe_config.h.
-
-[Compatibility Conditions]
-The following flags are defined automatically when using installation
-shell script.
-
-- AWE_OBSOLETE_VOXWARE		(default: not defined)
-    indicates the system is VoxWare-3.0.x (with linux 1.2.x or
-    FreeBSD) if defined.
-
-- AWE_NEW_KERNEL_INTERFACE	(default: not defined)
-    indicates the system is OSSLite on Linux 2.1.6 or later if
-    defined.
-
-- HAS_LOWLEVEL_H		(default: not defined)
-    indicates the system has "lowlevel.h" in the sound/lowlevel
-    directory.  OSS driver has this file.
-
-- AWE_NO_PATCHMGR		(default: not defined)
-    indicates the sound driver has no patch manager function (for
-    OSS-3.707 (in Linux-2.1.13) or newer). 
-
-- AWE_OSS38			(default: not defined)
-    indicates the sound driver has an additional parameter in
-    operation table (for OSS-3.8b5 in Linux-2.1.25 or newer).
-
-
-[Hardware Conditions]
-You don't have to define the following two values.
-Define them only when the driver couldn't detect the card properly.
-
-- AWE_DEFAULT_BASE_ADDR		(default: not defined)
-    specifies the base port address of your AWE32 card.
-
-- AWE_DEFAULT_MEM_SIZE		(default: not defined)
-    specifies the memory size of your AWE32 card in kilo bytes.
-    
-
-[Sample Table Size]
-From ver.0.4.0, sample tables are allocated dynamically (except
-Linux-1.2.x system), so you need NOT to touch these parameters.
-Linux-1.2.x users may need to increase these values for sound 
-cards equipped with more DRAM.
-
-- AWE_MAX_SF_LISTS, AWE_MAX_SAMPLES, AWE_MAX_INFOS
-
-
-[Other Conditions]
-
-- AWE_ALWAYS_INIT_FM		(default: not defined)
-    indicates the AWE driver always initialize FM passthrough even
-    without DRAM on board.  Emu8000 chip has a restriction for playing
-    samples on DRAM that at least two channels must be occupied as
-    passthrough channels. 
-
-- AWE_DEBUG_ON			(default: defined)
-    turns on debugging messages if defined.
-
-- AWE_HAS_GUS_COMPATIBILITY	(default: defined)
-    Enables GUS compatibility mode if defined, reading GUS patches and 
-    GUS control commands.  Define this option to use GMOD or other
-    GUS module players.
-
-- AWE_ACCEPT_ALL_SOUNDS_CONTROL	(default: defined)
-    Enables MIDI control #120 and #123 as "all notes off" and "all
-    sounds off" events, respectively.
-
-- CONFIG_AWE32_MIXER		(default: defined)
-    Adds a mixer device for AWE32 bass/treble equalizer control.
-    You can access this device using /dev/mixer?? (usually mixer01).
-
-- AWE_LOOKUP_MIDI_PRIORIITY	(default: defined)
-    Allocates voices according to MIDI channel priority.
-    Drum channels have the highest priorit, followed by #1, #2, and
-    so on.
-
-- DEF_FM_CHORUS_DEPTH		(default: 0x10)
-    The default strength to be sent to the chorus effect engine.
-    From 0 to 0xff.  Larger numbers may often cause weird sounds.
-
-- DEF_FM_REVERB_DEPTH		(default: 0x10)
-    The default strength to be sent to the reverb effect engine.
-    From 0 to 0xff.  Larger numbers may often cause weird sounds.
-
-
-* ACKNOWLEDGMENTS
-
-Thanks to Witold Jachimczyk (witek@xfactor.wpi.edu) for much advice
-on programming of AWE32.  Much code is brought from his AWE32-native 
-MOD player, ALMP.
-The port of awedrv to FreeBSD was done by Randall Hopper
-(rhh@ct.picker.com).
-I also thank linux-awe-ml members for their efforts
-to reboot their systems many times. :-)
-
-
-* BUGS & TODO'S
-
-- can't detect DRAM size on some cards
-- smarter patch management
-- smarter DRAM memory control
-- etc., etc., etc.
-
-
-* COPYRIGHT
-
-Copyright (C) 1996, 1997 Takashi Iwai
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-Takashi Iwai <iwai@dragon.mm.t.u-tokyo.ac.jp>
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_compat-fbsd.h linux/drivers/sound/lowlevel/awe_compat-fbsd.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_compat-fbsd.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/lowlevel/awe_compat-fbsd.h	Wed Dec 16 12:52:01 1998
@@ -0,0 +1,173 @@
+/*
+ * sound/awe_compat.h
+ *
+ * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
+ *   version 0.4.3; Nov. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_COMPAT_H_DEF
+#define AWE_COMPAT_H_DEF
+
+/*================================================================
+ * version check
+ *================================================================*/
+
+/* FreeBSD version check */
+#include <i386/isa/sound/awe_config.h>
+
+#define AWE_OBSOLETE_VOXWARE
+#if __FreeBSD__ >= 2
+#  include <osreldate.h>
+#  if __FreeBSD_version >= 300000
+#    undef AWE_OBSOLETE_VOXWARE
+#  endif
+#endif
+#ifdef __linux__
+#  include <linux/config.h>
+#endif
+
+
+/*================================================================
+ * INCLUDE OTHER HEADER FILES
+ *================================================================*/
+
+/* reading configuration of sound driver */
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include <i386/isa/sound/sound_config.h>
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#ifdef HAS_LOWLEVEL_H
+#include "lowlevel.h"
+#endif
+
+#include <i386/isa/sound/sound_config.h>
+#if defined(CONFIGURE_SOUNDCARD) && defined(CONFIG_AWE32)
+#  define CONFIG_AWE32_SYNTH
+#endif
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * include AWE header files
+ *================================================================*/
+
+#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
+
+#include <i386/isa/sound/awe_hw.h>
+#include <i386/isa/sound/awe_version.h>
+#include <i386/isa/sound/awe_voice.h>
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* include finetune table */
+#ifdef AWE_OBSOLETE_VOXWARE
+#  define SEQUENCER_C
+#endif
+#include <i386/isa/sound/tuning.h>
+#include <machine/ultrasound.h>
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
+/*----------------------------------------------------------------
+ * compatibility macros for AWE32 driver
+ *----------------------------------------------------------------*/
+
+/* redefine following macros */
+#undef IOCTL_IN
+#undef IOCTL_OUT
+#undef OUTW
+#undef COPY_FROM_USER
+#undef COPY_TO_USER
+#undef GET_BYTE_FROM_USER
+#undef GET_SHORT_FROM_USER
+#undef IOCTL_TO_USER
+  
+/* inline is not checked yet.. maybe it'll work */
+#define INLINE	/*inline*/
+
+#define KERN_WARNING /**/
+
+/*----------------------------------------------------------------
+ * memory management for freebsd
+ *----------------------------------------------------------------*/
+
+/* i/o requests; nothing */
+#define awe_check_port()	0	/* always false */
+#define awe_request_region()	/* nothing */
+#define awe_release_region()	/* nothing */
+
+#define AWE_DYNAMIC_BUFFER
+
+#define my_malloc_init(ptr)	/* nothing */
+#define my_malloc_memptr()	0
+#define my_malloc(size)		malloc(size, M_TEMP, M_WAITOK)
+#define my_free(ptr)		if (ptr) {free(ptr, M_TEMP);}
+
+#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
+
+/*----------------------------------------------------------------
+ * i/o interfaces for freebsd
+ *----------------------------------------------------------------*/
+
+/* according to linux rule; the arguments are swapped */
+#define OUTW(data,addr)		outw(addr, data)
+
+#define COPY_FROM_USER(target,source,offs,count) \
+	uiomove(((caddr_t)(target)),(count),((struct uio *)(source)))
+#define COPY_TO_USER(target,source,offs,count) \
+	uiomove(((caddr_t)(source)),(count),((struct uio *)(target)))
+#define GET_BYTE_FROM_USER(target,addr,offs) \
+	uiomove(((char*)&(target)), 1, ((struct uio *)(addr)))
+#define GET_SHORT_FROM_USER(target,addr,offs) \
+	uiomove(((char*)&(target)), 2, ((struct uio *)(addr)))
+#define IOCTL_TO_USER(target,offs,source,count) \
+	memcpy(&((target)[offs]), (source), (count))
+#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
+#define IOCTL_IN(arg)		(*(int*)(arg))
+#define IOCTL_OUT(arg,val)	(*(int*)(arg) = (val))
+#define BZERO(target,len)	bzero((caddr_t)target, len)
+#define MEMCPY(dst,src,len)	bcopy((caddr_t)src, (caddr_t)dst, len)
+
+#ifndef AWE_OBSOLETE_VOXWARE
+#  define printk printf
+#  define RET_ERROR(err)		-err
+#endif
+
+
+/* old style device tables (not modulized) */
+#define sound_alloc_synthdev() \
+	(num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
+#define sound_alloc_mixerdev() \
+	(num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
+#define sound_alloc_mididev() \
+	(num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
+#define sound_unload_synthdev(dev)	/**/
+#define sound_unload_mixerdev(dev)	/**/
+#define sound_unload_mididev(dev)	/**/
+
+
+#endif /* CONFIG_AWE32_SYNTH */
+
+#endif /* AWE_COMPAT_H_DEF */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_compat-linux.h linux/drivers/sound/lowlevel/awe_compat-linux.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_compat-linux.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/lowlevel/awe_compat-linux.h	Wed Dec 16 12:52:01 1998
@@ -0,0 +1,248 @@
+/*
+ * sound/awe_compat.h
+ *
+ * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
+ *   version 0.4.3; Oct. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_COMPAT_H_DEF
+#define AWE_COMPAT_H_DEF
+
+/*================================================================
+ * version check
+ *================================================================*/
+
+#include "awe_config.h"
+
+#define ASC_LINUX_VERSION(V,P,S)    (((V) * 65536) + ((P) * 256) + (S))
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+/* linux version check */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+#define AWE_OBSOLETE_VOXWARE
+#endif
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
+#define AWE_NEW_KERNEL_INTERFACE
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,80)
+#define AWE_MODULE_SUPPORT
+#endif
+#endif
+
+#ifdef AWE_OBSOLETE_VOXWARE
+#include "soundvers.h"
+#else
+#include "../soundvers.h"
+#endif
+
+#if defined(SOUND_INTERNAL_VERSION) && SOUND_INTERNAL_VERSION >= 0x30803
+/* OSS/Free-3.8 */
+#define AWE_NO_PATCHMGR
+#define AWE_OSS38
+#define HAS_LOWLEVEL_H
+#endif
+
+/*================================================================
+ * INCLUDE OTHER HEADER FILES
+ *================================================================*/
+
+/* set up module */
+
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include "../soundmodule.h"
+#endif
+
+
+/* reading configuration of sound driver */
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include "sound_config.h"
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#ifdef HAS_LOWLEVEL_H
+#include "lowlevel.h"
+#endif
+
+#include "../sound_config.h"
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * include AWE header files
+ *================================================================*/
+
+#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
+
+#include "awe_hw.h"
+#include "awe_version.h"
+#include <linux/awe_voice.h>
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* include finetune table */
+#ifdef AWE_OBSOLETE_VOXWARE
+#  include "tuning.h"
+#else
+#  include "../tuning.h"
+#endif
+#include <linux/ultrasound.h>
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
+/*----------------------------------------------------------------
+ * compatibility macros for AWE32 driver
+ *----------------------------------------------------------------*/
+
+/* redefine following macros */
+#undef IOCTL_IN
+#undef IOCTL_OUT
+#undef OUTW
+#undef COPY_FROM_USER
+#undef COPY_TO_USER
+#undef GET_BYTE_FROM_USER
+#undef GET_SHORT_FROM_USER
+#undef IOCTL_TO_USER
+  
+/* use inline prefix */
+#define INLINE	inline
+
+/*----------------------------------------------------------------
+ * memory management for linux
+ *----------------------------------------------------------------*/
+
+#ifdef AWE_OBSOLETE_VOXWARE
+/* old type linux system */
+
+/* i/o requests; nothing */
+#define awe_check_port()	0	/* always false */
+#define awe_request_region()	/* nothing */
+#define awe_release_region()	/* nothing */
+
+static int _mem_start;  /* memory pointer for permanent buffers */
+
+#define my_malloc_init(memptr)	_mem_start = (memptr)
+#define my_malloc_memptr()	_mem_start
+#define my_free(ptr)	/* do nothing */
+
+/* allocate buffer only once */
+#define INIT_TABLE(buffer,index,nums,type) {\
+PERMANENT_MALLOC(buffer, char*, size, _mem_start); index = (nums);\
+}
+
+#else
+
+#define AWE_DYNAMIC_BUFFER
+
+#define my_malloc_init(ptr)	/* nothing */
+#define my_malloc_memptr()	0
+#define my_malloc(size)		vmalloc(size)
+#define my_free(ptr)		if (ptr) {vfree(ptr);}
+
+/* do not allocate buffer at beginning */
+#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
+
+/* old type macro */
+#define RET_ERROR(err)		-err
+
+#endif
+
+/*----------------------------------------------------------------
+ * i/o interfaces for linux
+ *----------------------------------------------------------------*/
+
+#define OUTW(data,addr)		outw(data, addr)
+
+#ifdef AWE_NEW_KERNEL_INTERFACE
+#define COPY_FROM_USER(target,source,offs,count) \
+	copy_from_user(target, (source)+(offs), count)
+#define GET_BYTE_FROM_USER(target,addr,offs) \
+	get_user(target, (unsigned char*)&((addr)[offs]))
+#define GET_SHORT_FROM_USER(target,addr,offs) \
+	get_user(target, (unsigned short*)&((addr)[offs]))
+#ifdef AWE_OSS38
+#define IOCTL_TO_USER(target,offs,source,count) \
+	memcpy(target, (source)+(offs), count)
+#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
+#else
+#define IOCTL_TO_USER(target,offs,source,count) \
+	copy_to_user(target, (source)+(offs), count)
+#define IO_WRITE_CHECK(cmd)	(_IOC_DIR(cmd) & _IOC_WRITE)
+#endif /* AWE_OSS38 */
+#define COPY_TO_USER	IOCTL_TO_USER
+#define IOCTL_IN(arg)	(*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+
+#else /* old type i/o */
+#define COPY_FROM_USER(target,source,offs,count) \
+	memcpy_fromfs(target, (source)+(offs), (count))
+#define GET_BYTE_FROM_USER(target,addr,offs) \
+	*((char  *)&(target)) = get_fs_byte((addr)+(offs))
+#define GET_SHORT_FROM_USER(target,addr,offs) \
+	*((short *)&(target)) = get_fs_word((addr)+(offs))
+#ifdef AWE_OSS38
+#define IOCTL_TO_USER(target,offs,source,count) \
+	memcpy(target, (source)+(offs), count)
+#define COPY_TO_USER(target,offs,source,count)  \
+	memcpy_tofs(target, (source)+(offs), (count))
+#define IOCTL_IN(arg)	(*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
+#else /* AWE_OSS38 */
+#define IOCTL_TO_USER(target,offs,source,count) \
+	memcpy_tofs(target, (source)+(offs), (count))
+#define COPY_TO_USER	IOCTL_TO_USER
+#define IOCTL_IN(arg)		get_fs_long((long *)(arg))
+#define IOCTL_OUT(arg,ret)	snd_ioctl_return((int *)arg, ret)
+#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
+#endif /* AWE_OSS38 */
+
+#endif /* AWE_NEW_KERNEL_INTERFACE */
+
+#define BZERO(target,len)	memset(target, 0, len)
+#define MEMCPY(dst,src,len)	memcpy(dst, src, len)
+
+/* old style device tables (not modulized) */
+#ifndef AWE_MODULE_SUPPORT
+
+#define sound_alloc_synthdev() \
+	(num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
+#define sound_alloc_mixerdev() \
+	(num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
+#define sound_alloc_mididev() \
+	(num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
+#define sound_unload_synthdev(dev)	/**/
+#define sound_unload_mixerdev(dev)	/**/
+#define sound_unload_mididev(dev)	/**/
+
+#endif /* AWE_MODULE_SUPPORT */
+
+#endif /* CONFIG_AWE32_SYNTH */
+
+#endif /* AWE_COMPAT_H_DEF */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_compat.h linux/drivers/sound/lowlevel/awe_compat.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_compat.h	Sat Sep  5 16:46:41 1998
+++ linux/drivers/sound/lowlevel/awe_compat.h	Wed Dec 16 12:52:01 1998
@@ -1,3 +1,121 @@
+/*
+ * sound/awe_compat.h
+ *
+ * Compat defines for the AWE32/SB32/AWE64 wave table synth driver.
+ *   version 0.4.3; Oct. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef AWE_COMPAT_H_DEF
+#define AWE_COMPAT_H_DEF
+
+/*================================================================
+ * version check
+ *================================================================*/
+
+#include "awe_config.h"
+
+#define ASC_LINUX_VERSION(V,P,S)    (((V) * 65536) + ((P) * 256) + (S))
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#endif
+
+/* linux version check */
+#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,0,0)
+#define AWE_OBSOLETE_VOXWARE
+#endif
+
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,0)
+#define AWE_NEW_KERNEL_INTERFACE
+#if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,1,80)
+#define AWE_MODULE_SUPPORT
+#endif
+#endif
+
+#ifdef AWE_OBSOLETE_VOXWARE
+#include "soundvers.h"
+#else
+#include "../soundvers.h"
+#endif
+
+#if SOUND_INTERNAL_VERSION >= 0x30803
+/* OSS/Free-3.8 */
+#define AWE_NO_PATCHMGR
+#define AWE_OSS38
+#define HAS_LOWLEVEL_H
+#endif
+
+/*================================================================
+ * INCLUDE OTHER HEADER FILES
+ *================================================================*/
+
+/* set up module */
+
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include "../soundmodule.h"
+#endif
+
+
+/* reading configuration of sound driver */
+
+#ifdef AWE_OBSOLETE_VOXWARE
+
+#include "sound_config.h"
+#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
+#define CONFIG_AWE32_SYNTH
+#endif
+
+#else /* AWE_OBSOLETE_VOXWARE */
+
+#ifdef HAS_LOWLEVEL_H
+#include "lowlevel.h"
+#endif
+
+#include "../sound_config.h"
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+
+/*================================================================
+ * include AWE header files
+ *================================================================*/
+
+#if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
+
+#include "awe_hw.h"
+#include "awe_version.h"
+#include <linux/awe_voice.h>
+
+#ifdef AWE_HAS_GUS_COMPATIBILITY
+/* include finetune table */
+#ifdef AWE_OBSOLETE_VOXWARE
+#  include "tuning.h"
+#else
+#  include "../tuning.h"
+#endif
+#include <linux/ultrasound.h>
+#endif /* AWE_HAS_GUS_COMPATIBILITY */
+
+
 /*----------------------------------------------------------------
  * compatibility macros for AWE32 driver
  *----------------------------------------------------------------*/
@@ -12,14 +130,8 @@
 #undef GET_SHORT_FROM_USER
 #undef IOCTL_TO_USER
   
-#ifdef linux
-
-/*================================================================
- * Linux macros
- *================================================================*/
-
 /* use inline prefix */
-#define INLINE	inline
+#define INLINE	/*inline*/
 
 /*----------------------------------------------------------------
  * memory management for linux
@@ -46,6 +158,8 @@
 	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) {\
@@ -60,6 +174,8 @@
 #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)
 
 static void *my_realloc(void *buf, int oldsize, int size)
 {
@@ -92,7 +208,7 @@
 	get_user(target, (unsigned char*)&((addr)[offs]))
 #define GET_SHORT_FROM_USER(target,addr,offs) \
 	get_user(target, (unsigned short*)&((addr)[offs]))
-#ifdef AWE_OSS38_AND_IM_A_BANANA
+#ifdef AWE_OSS38
 #define IOCTL_TO_USER(target,offs,source,count) \
 	memcpy(target, (source)+(offs), count)
 #define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
@@ -112,79 +228,44 @@
 	*((char  *)&(target)) = get_fs_byte((addr)+(offs))
 #define GET_SHORT_FROM_USER(target,addr,offs) \
 	*((short *)&(target)) = get_fs_word((addr)+(offs))
+#ifdef AWE_OSS38
+#define IOCTL_TO_USER(target,offs,source,count) \
+	memcpy(target, (source)+(offs), count)
+#define COPY_TO_USER(target,offs,source,count)  \
+	memcpy_tofs(target, (source)+(offs), (count))
+#define IOCTL_IN(arg)	(*(int*)(arg))
+#define IOCTL_OUT(arg,val) (*(int*)(arg) = (val))
+#define IO_WRITE_CHECK(cmd)	(_SIOC_DIR(cmd) & _IOC_WRITE)
+#else /* AWE_OSS38 */
 #define IOCTL_TO_USER(target,offs,source,count) \
 	memcpy_tofs(target, (source)+(offs), (count))
 #define COPY_TO_USER	IOCTL_TO_USER
-#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
 #define IOCTL_IN(arg)		get_fs_long((long *)(arg))
 #define IOCTL_OUT(arg,ret)	snd_ioctl_return((int *)arg, ret)
+#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
+#endif /* AWE_OSS38 */
 
 #endif /* AWE_NEW_KERNEL_INTERFACE */
 
 #define BZERO(target,len)	memset(target, 0, len)
 #define MEMCPY(dst,src,len)	memcpy(dst, src, len)
+#define MEMCMP(p1,p2,len)	memcmp(p1, p2, len)
 
+/* old style device tables (not modulized) */
+#ifndef AWE_MODULE_SUPPORT
 
-#elif defined(__FreeBSD__)
-
-/*================================================================
- * FreeBSD macros
- *================================================================*/
-
-/* inline is not checked yet.. maybe it'll work */
-#define INLINE	/*inline*/
-
-/*----------------------------------------------------------------
- * memory management for freebsd
- *----------------------------------------------------------------*/
-
-/* i/o requests; nothing */
-#define awe_check_port()	0	/* always false */
-#define awe_request_region()	/* nothing */
-#define awe_release_region()	/* nothing */
-
-#define AWE_DYNAMIC_BUFFER
-
-#define my_malloc_init(ptr)	/* nothing */
-#define my_malloc_memptr()	0
-#define my_malloc(size)		malloc(size, M_TEMP, M_WAITOK)
-#define my_free(ptr)		if (ptr) {free(ptr, M_TEMP);}
+#define sound_alloc_synthdev() \
+	(num_synths >= MAX_SYNTH_DEV ? -1 : num_synths++)
+#define sound_alloc_mixerdev() \
+	(num_mixers >= MAX_MIXER_DEV ? -1 : num_mixers++)
+#define sound_alloc_mididev() \
+	(num_midis >= MAX_MIXER_DEV ? -1 : num_midis++)
+#define sound_unload_synthdev(dev)	/**/
+#define sound_unload_mixerdev(dev)	/**/
+#define sound_unload_mididev(dev)	/**/
 
-#define INIT_TABLE(buffer,index,nums,type) {buffer=NULL; index=0;}
+#endif /* AWE_MODULE_SUPPORT */
 
-/* it should be realloc? */
-static void *my_realloc(void *buf, int oldsize, int size)
-{
-	void *ptr;
-	if ((ptr = my_malloc(size)) == NULL)
-		return NULL;
-	memcpy(ptr, buf, ((oldsize < size) ? oldsize : size) );
-	my_free(buf);
-	return ptr;
-}
-
-/*----------------------------------------------------------------
- * i/o interfaces for freebsd
- *----------------------------------------------------------------*/
-
-/* according to linux rule; the arguments are swapped */
-#define OUTW(data,addr)		outw(addr, data)
-
-#define COPY_FROM_USER(target,source,offs,count) \
-	uiomove(((caddr_t)(target)),(count),((struct uio *)(source)))
-#define COPY_TO_USER(target,source,offs,count) \
-	uiomove(((caddr_t)(source)),(count),((struct uio *)(target)))
-#define GET_BYTE_FROM_USER(target,addr,offs) \
-	uiomove(((char*)&(target)), 1, ((struct uio *)(addr)))
-#define GET_SHORT_FROM_USER(target,addr,offs) \
-	uiomove(((char*)&(target)), 2, ((struct uio *)(addr)))
-#define IOCTL_TO_USER(target,offs,source,count) \
-	memcpy(&((target)[offs]), (source), (count))
-#define IO_WRITE_CHECK(cmd)	(cmd & IOC_IN)
-#define IOCTL_IN(arg)		(*(int*)(arg))
-#define IOCTL_OUT(arg,val)	(*(int*)(arg) = (val))
-#define BZERO(target,len)	bzero((caddr_t)target, len)
-#define MEMCPY(dst,src,len)	bcopy((caddr_t)src, (caddr_t)dst, len)
-
-#endif
+#endif /* CONFIG_AWE32_SYNTH */
 
+#endif /* AWE_COMPAT_H_DEF */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_config.h linux/drivers/sound/lowlevel/awe_config.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_config.h	Sat Nov 29 10:33:20 1997
+++ linux/drivers/sound/lowlevel/awe_config.h	Wed Dec 16 12:52:01 1998
@@ -1,10 +1,10 @@
 /*
  * sound/awe_config.h
  *
- * Configuration of AWE32 sound driver
- *   version 0.4.2; Sep. 15, 1997
+ * Configuration of AWE32/SB32/AWE64 wave table synth driver.
+ *   version 0.4.3; Mar. 1, 1998
  *
- * Copyright (C) 1996 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,60 +28,12 @@
  * system configuration
  *----------------------------------------------------------------*/
 
-/* if you're using obsolete VoxWare 3.0.x on Linux 1.2.x (or FreeBSD),
- * define the following line.
+/* if your kernel support module for each soundcard, define this.
+ * NOTE: it will be automatically set on linux-2.1.x kernels.
+ *       only define here if you have moduler sound system on
+ *       2.0.x kernel (like RedHat).
  */
-#undef AWE_OBSOLETE_VOXWARE
-
-#ifdef __FreeBSD__
-#  define AWE_OBSOLETE_VOXWARE
-#endif
-
-/* if you're using OSS-Lite on Linux 2.1.6 or later, define the
- * following line.
- */
-#define AWE_NEW_KERNEL_INTERFACE
-
-/* if you have lowlevel.h in the lowlevel directory (OSS-Lite), define
- * the following line.
- */
-#define HAS_LOWLEVEL_H
-
-/* if your system doesn't support patch manager (OSS 3.7 or newer),
- * define the following line.
- */
-#define AWE_NO_PATCHMGR
- 
-/* if your system has an additional parameter (OSS 3.8b5 or newer),
- * define this.
- */
-#define AWE_OSS38
-
-/*----------------------------------------------------------------
- * AWE32 card configuration:
- * uncomment the following lines only when auto detection doesn't
- * work properly on your machine.
- *----------------------------------------------------------------*/
-
-/*#define AWE_DEFAULT_BASE_ADDR	0x620*/	/* base port address */
-/*#define AWE_DEFAULT_MEM_SIZE	512*/	/* kbytes */
-
-
-/*----------------------------------------------------------------
- * maximum size of soundfont list table:
- * you usually don't need to touch this value.
- *----------------------------------------------------------------*/
-
-#define AWE_MAX_SF_LISTS 16
-
-
-/*----------------------------------------------------------------
- * chunk size of sample and voice tables:
- * you usually don't need to touch these values.
- *----------------------------------------------------------------*/
-
-#define AWE_MAX_SAMPLES 400
-#define AWE_MAX_INFOS 800
+#undef AWE_MODULE_SUPPORT
 
 
 /*----------------------------------------------------------------
@@ -106,40 +58,45 @@
 /* GUS compatible mode */
 #define AWE_HAS_GUS_COMPATIBILITY
 
-/* accept all notes/sounds off controls */
-#define AWE_ACCEPT_ALL_SOUNDS_CONTROL
+/* add MIDI emulation by wavetable */
+#define CONFIG_AWE32_MIDIEMU
 
 /* add mixer control of emu8000 equalizer */
-#define CONFIG_AWE32_MIXER
-
-/* look up voices according to MIDI channel priority */
-#define AWE_LOOKUP_MIDI_PRIORITY
+#undef CONFIG_AWE32_MIXER
 
-/*----------------------------------------------------------------*/
+/* use new volume calculation method as default */
+#define AWE_USE_NEW_VOLUME_CALC
 
-/* reading configuration of sound driver */
+/* check current volume target for searching empty voices */
+#define AWE_CHECK_VTARGET
 
-#ifdef AWE_OBSOLETE_VOXWARE
+/* allow sample sharing */
+#define AWE_ALLOW_SAMPLE_SHARING
 
-#ifdef __FreeBSD__
-#  include <i386/isa/sound/sound_config.h>
-#else
-#  include "sound_config.h"
-#endif
+/*================================================================
+ * Usually, you don't have to touch the following options.
+ *================================================================*/
 
-#if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_AWE32)
-#define CONFIG_AWE32_SYNTH
-#endif
+/*----------------------------------------------------------------
+ * AWE32 card configuration:
+ * uncomment the following lines *ONLY* when auto detection doesn't
+ * work properly on your machine.
+ *----------------------------------------------------------------*/
 
-#else /* AWE_OBSOLETE_VOXWARE */
+/*#define AWE_DEFAULT_BASE_ADDR	0x620*/	/* base port address */
+/*#define AWE_DEFAULT_MEM_SIZE	512*/	/* kbytes */
 
-#ifdef HAS_LOWLEVEL_H
-#include "lowlevel.h"
-#endif
+/*----------------------------------------------------------------
+ * maximum size of soundfont list table
+ *----------------------------------------------------------------*/
 
-#include "../sound_config.h"
+#define AWE_MAX_SF_LISTS 16
 
-#endif /* AWE_OBSOLETE_VOXWARE */
+/*----------------------------------------------------------------
+ * chunk size of sample and voice tables
+ *----------------------------------------------------------------*/
 
+#define AWE_MAX_SAMPLES 400
+#define AWE_MAX_INFOS 800
 
 #endif  /* AWE_CONFIG_H_DEF */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_hw.h linux/drivers/sound/lowlevel/awe_hw.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_hw.h	Sat Nov 29 10:33:20 1997
+++ linux/drivers/sound/lowlevel/awe_hw.h	Wed Dec 16 12:52:01 1998
@@ -2,10 +2,10 @@
  * sound/awe_hw.h
  *
  * Access routines and definitions for the low level driver for the 
- * AWE32/Sound Blaster 32 wave table synth.
- *   version 0.4.2; Sep. 15, 1997
+ * Creative AWE32/SB32/AWE64 wave table synth.
+ *   version 0.4.3; Mar. 1, 1998
  *
- * Copyright (C) 1996,1997 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -32,16 +32,18 @@
 
 #define awe_cmd_idx(reg,ch)	(((reg)<< 5) | (ch))
 
-#define Data0    0x620	/* doubleword r/w */
-#define Data1    0xA20	/* doubleword r/w */
-#define Data2    0xA22	/* word r/w */
-#define Data3    0xE20	/* word r/w */
-#define Pointer  0xE22	/* register pointer r/w */
+#define Data0    0		/* 0x620: doubleword r/w */
+#define Data1    1		/* 0xA20: doubleword r/w */
+#define Data2    2		/* 0xA22: word r/w */
+#define Data3    3		/* 0xE20: word r/w */
+#define Pointer  4		/* 0xE22 register pointer r/w */
 
 #define AWE_CPF(ch)	awe_cmd_idx(0,ch), Data0	/* DW: current pitch and fractional address */
 #define AWE_PTRX(ch)	awe_cmd_idx(1,ch), Data0	/* DW: pitch target and reverb send */
 #define AWE_CVCF(ch)	awe_cmd_idx(2,ch), Data0	/* DW: current volume and filter cutoff */
 #define AWE_VTFT(ch)	awe_cmd_idx(3,ch), Data0	/* DW: volume and filter cutoff targets */
+#define AWE_0080(ch)	awe_cmd_idx(4,ch), Data0	/* DW: ?? */
+#define AWE_00A0(ch)	awe_cmd_idx(5,ch), Data0	/* DW: ?? */
 #define AWE_PSST(ch)	awe_cmd_idx(6,ch), Data0	/* DW: pan send and loop start address */
 #define AWE_CSL(ch)	awe_cmd_idx(7,ch), Data0	/* DW: chorus send and loop end address */
 #define AWE_CCCA(ch)	awe_cmd_idx(0,ch), Data1	/* DW: Q, control bits, and current address */
@@ -93,8 +95,5 @@
 
 #define AWE_DRAM_OFFSET		0x200000
 #define AWE_MAX_DRAM_SIZE	(28 * 1024)	/* 28 MB is max onboard memory */
-
-#define AWE_DEFAULT_ATTENUATION	32	/* 12dB below */
-#define AWE_DEFAULT_MOD_SENSE	18
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_version.h linux/drivers/sound/lowlevel/awe_version.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_version.h	Sun Jan  4 10:40:16 1998
+++ linux/drivers/sound/lowlevel/awe_version.h	Wed Dec 16 12:52:01 1998
@@ -1,13 +1,35 @@
+/*
+ * sound/awe_version.h
+ *
+ * Version defines for the AWE32/SB32/AWE64 wave table synth driver.
+ *   version 0.4.3; Mar. 1, 1998
+ *
+ * Copyright (C) 1996-1998 Takashi Iwai
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
 /* AWE32 driver version number */
 
 #ifndef AWE_VERSION_H_DEF
 #define AWE_VERSION_H_DEF
 
-#define AWE_VERSION_NUMBER	0x00040203
-#define AWEDRV_VERSION		"0.4.2c"
-#define AWE_MAJOR_VERSION(id)	(((id) >> 16) & 0xff)
-#define AWE_MINOR_VERSION(id)	(((id) >> 8) & 0xff)
-#define AWE_TINY_VERSION(id)	((id) & 0xff)
+#define AWE_MAJOR_VERSION	0
+#define AWE_MINOR_VERSION	4
+#define AWE_TINY_VERSION	3
+#define AWE_VERSION_NUMBER	((AWE_MAJOR_VERSION<<16)|(AWE_MINOR_VERSION<<8)|AWE_TINY_VERSION)
+#define AWEDRV_VERSION		"0.4.3"
 
 #endif
-
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_voice.h linux/drivers/sound/lowlevel/awe_voice.h
--- v2.1.131/linux/drivers/sound/lowlevel/awe_voice.h	Sat Nov 29 10:33:20 1997
+++ linux/drivers/sound/lowlevel/awe_voice.h	Wed Dec 31 16:00:00 1969
@@ -1,490 +0,0 @@
-/*
- * sound/awe_voice.h
- *
- * Voice information definitions for the low level driver for the 
- * AWE32/Sound Blaster 32 wave table synth.
- *   version 0.4.2c; Oct. 7, 1997
- *
- * Copyright (C) 1996,1997 Takashi Iwai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef AWE_VOICE_H
-#define AWE_VOICE_H
-
-#ifndef SAMPLE_TYPE_AWE32
-#define SAMPLE_TYPE_AWE32	0x20
-#endif
-
-#ifndef _PATCHKEY
-#define _PATCHKEY(id) ((id<<8)|0xfd)
-#endif
-
-/*----------------------------------------------------------------
- * patch information record
- *----------------------------------------------------------------*/
-
-/* patch interface header: 16 bytes */
-typedef struct awe_patch_info {
-	short key;			/* use AWE_PATCH here */
-#define AWE_PATCH	_PATCHKEY(0x07)
-
-	short device_no;		/* synthesizer number */
-	unsigned short sf_id;		/* file id (should be zero) */
-	short optarg;			/* optional argument */
-	int len;			/* data length (without this header) */
-
-	short type;			/* patch operation type */
-#define AWE_LOAD_INFO		0	/* awe_voice_rec */
-#define AWE_LOAD_DATA		1	/* awe_sample_info */
-#define AWE_OPEN_PATCH		2	/* awe_open_parm */
-#define AWE_CLOSE_PATCH		3	/* none */
-#define AWE_UNLOAD_PATCH	4	/* none */
-#define AWE_REPLACE_DATA	5	/* awe_sample_info (optarg=#channels)*/
-#define AWE_MAP_PRESET		6	/* awe_voice_map */
-#define AWE_LOAD_CHORUS_FX	0x10	/* awe_chorus_fx_rec (optarg=mode) */
-#define AWE_LOAD_REVERB_FX	0x11	/* awe_reverb_fx_rec (optarg=mode) */
-
-	short reserved;			/* word alignment data */
-
-	/* the actual patch data begins after this */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-	char data[0];
-#endif
-} awe_patch_info;
-
-/*#define AWE_PATCH_INFO_SIZE	16*/
-#define AWE_PATCH_INFO_SIZE	sizeof(awe_patch_info)
-
-
-/*----------------------------------------------------------------
- * open patch
- *----------------------------------------------------------------*/
-
-#define AWE_PATCH_NAME_LEN	32
-
-typedef struct _awe_open_parm {
-	unsigned short type;		/* sample type */
-#define AWE_PAT_TYPE_MISC	0
-#define AWE_PAT_TYPE_GM		1
-#define AWE_PAT_TYPE_GS		2
-#define AWE_PAT_TYPE_MT32	3
-#define AWE_PAT_TYPE_XG		4
-#define AWE_PAT_TYPE_SFX	5
-#define AWE_PAT_TYPE_GUS	6
-#define AWE_PAT_TYPE_MAP	7
-
-#define AWE_PAT_LOCKED		0x100	/* lock the samples */
-
-	short reserved;
-	char name[AWE_PATCH_NAME_LEN];
-} awe_open_parm;
-
-/*#define AWE_OPEN_PARM_SIZE	28*/
-#define AWE_OPEN_PARM_SIZE	sizeof(awe_open_parm)
-
-
-/*----------------------------------------------------------------
- * raw voice information record
- *----------------------------------------------------------------*/
-
-/* wave table envelope & effect parameters to control EMU8000 */
-typedef struct _awe_voice_parm {
-	unsigned short moddelay;	/* modulation delay (0x8000) */
-	unsigned short modatkhld;	/* modulation attack & hold time (0x7f7f) */
-	unsigned short moddcysus;	/* modulation decay & sustain (0x7f7f) */
-	unsigned short modrelease;	/* modulation release time (0x807f) */
-	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
-	unsigned short voldelay;	/* volume delay (0x8000) */
-	unsigned short volatkhld;	/* volume attack & hold time (0x7f7f) */
-	unsigned short voldcysus;	/* volume decay & sustain (0x7f7f) */
-	unsigned short volrelease;	/* volume release time (0x807f) */
-	short volkeyhold, volkeydecay;	/* envelope change per key (not used) */
-	unsigned short lfo1delay;	/* LFO1 delay (0x8000) */
-	unsigned short lfo2delay;	/* LFO2 delay (0x8000) */
-	unsigned short pefe;		/* modulation pitch & cutoff (0x0000) */
-	unsigned short fmmod;		/* LFO1 pitch & cutoff (0x0000) */
-	unsigned short tremfrq;		/* LFO1 volume & freq (0x0000) */
-	unsigned short fm2frq2;		/* LFO2 pitch & freq (0x0000) */
-	unsigned char cutoff;		/* initial cutoff (0xff) */
-	unsigned char filterQ;		/* initial filter Q [0-15] (0x0) */
-	unsigned char chorus;		/* chorus send (0x00) */
-	unsigned char reverb;		/* reverb send (0x00) */
-	unsigned short reserved[4];	/* not used */
-} awe_voice_parm;
-
-#define AWE_VOICE_PARM_SIZE	48
-
-
-/* wave table parameters: 92 bytes */
-typedef struct _awe_voice_info {
-	unsigned short sf_id;		/* file id (should be zero) */
-	unsigned short sample;		/* sample id */
-	int start, end;			/* sample offset correction */
-	int loopstart, loopend;		/* loop offset correction */
-	short rate_offset;		/* sample rate pitch offset */
-	unsigned short mode;		/* sample mode */
-#define AWE_MODE_ROMSOUND		0x8000
-#define AWE_MODE_STEREO			1
-#define AWE_MODE_LOOPING		2
-#define AWE_MODE_NORELEASE		4	/* obsolete */
-#define AWE_MODE_INIT_PARM		8
-
-	short root;			/* midi root key */
-	short tune;			/* pitch tuning (in cents) */
-	char low, high;			/* key note range */
-	char vellow, velhigh;		/* velocity range */
-	char fixkey, fixvel;		/* fixed key, velocity */
-	char pan, fixpan;		/* panning, fixed panning */
-	short exclusiveClass;		/* exclusive class (0 = none) */
-	unsigned char amplitude;	/* sample volume (127 max) */
-	unsigned char attenuation;	/* attenuation (0.375dB) */
-	short scaleTuning;		/* pitch scale tuning(%), normally 100 */
-	awe_voice_parm parm;		/* voice envelope parameters */
-	short index;			/* internal index (set by driver) */
-} awe_voice_info;
-
-/*#define AWE_VOICE_INFO_SIZE	92*/
-#define AWE_VOICE_INFO_SIZE	sizeof(awe_voice_info)
-
-/*----------------------------------------------------------------*/
-
-/* The info entry of awe_voice_rec is changed from 0 to 1
- * for some compilers refusing zero size array.
- * Due to this change, sizeof(awe_voice_rec) becomes different
- * from older versions.
- * Use AWE_VOICE_REC_SIZE instead.
- */
-
-/* instrument info header: 4 bytes */
-typedef struct _awe_voice_rec_hdr {
-	unsigned char bank;		/* midi bank number */
-	unsigned char instr;		/* midi preset number */
-	char nvoices;			/* number of voices */
-	char write_mode;		/* write mode; normally 0 */
-#define AWE_WR_APPEND		0	/* append anyway */
-#define AWE_WR_EXCLUSIVE	1	/* skip if already exists */
-#define AWE_WR_REPLACE		2	/* replace if already exists */
-} awe_voice_rec_hdr;
-
-/*#define AWE_VOICE_REC_SIZE	4*/
-#define AWE_VOICE_REC_SIZE	sizeof(awe_voice_rec_hdr)
-
-/* the standard patch structure for one sample */
-typedef struct _awe_voice_rec_patch {
-	awe_patch_info		patch;
-	awe_voice_rec_hdr	hdr;
-	awe_voice_info		info;
-} awe_voice_rec_patch;
-
-
-/* obsolete data type */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-#define AWE_INFOARRAY_SIZE	0
-#else
-#define AWE_INFOARRAY_SIZE	1
-#endif
-
-typedef struct _awe_voice_rec {
-	unsigned char bank;		/* midi bank number */
-	unsigned char instr;		/* midi preset number */
-	short nvoices;			/* number of voices */
-	/* voice information follows here */
-	awe_voice_info info[AWE_INFOARRAY_SIZE];
-} awe_voice_rec;
-
-
-/*----------------------------------------------------------------
- * sample wave information
- *----------------------------------------------------------------*/
-
-/* wave table sample header: 32 bytes */
-typedef struct awe_sample_info {
-	unsigned short sf_id;		/* file id (should be zero) */
-	unsigned short sample;		/* sample id */
-	int start, end;			/* start & end offset */
-	int loopstart, loopend;		/* loop start & end offset */
-	int size;			/* size (0 = ROM) */
-	short checksum_flag;		/* use check sum = 1 */
-	unsigned short mode_flags;	/* mode flags */
-#define AWE_SAMPLE_8BITS	1	/* wave data is 8bits */
-#define AWE_SAMPLE_UNSIGNED	2	/* wave data is unsigned */
-#define AWE_SAMPLE_NO_BLANK	4	/* no blank loop is attached */
-#define AWE_SAMPLE_SINGLESHOT	8	/* single-shot w/o loop */
-#define AWE_SAMPLE_BIDIR_LOOP	16	/* bidirectional looping */
-#define AWE_SAMPLE_STEREO_LEFT	32	/* stereo left sound */
-#define AWE_SAMPLE_STEREO_RIGHT	64	/* stereo right sound */
-#define AWE_SAMPLE_REVERSE_LOOP 128	/* reverse looping */
-	unsigned int checksum;		/* check sum */
-#if defined(AWE_COMPAT_030) && AWE_COMPAT_030
-	unsigned short data[0];		/* sample data follows here */
-#endif
-} awe_sample_info;
-
-/*#define AWE_SAMPLE_INFO_SIZE	32*/
-#define AWE_SAMPLE_INFO_SIZE	sizeof(awe_sample_info)
-
-
-/*----------------------------------------------------------------
- * voice preset mapping
- *----------------------------------------------------------------*/
-
-typedef struct awe_voice_map {
-	int map_bank, map_instr, map_key;	/* key = -1 means all keys */
-	int src_bank, src_instr, src_key;
-} awe_voice_map;
-
-#define AWE_VOICE_MAP_SIZE	sizeof(awe_voice_map)
-
-
-/*----------------------------------------------------------------
- * awe hardware controls
- *----------------------------------------------------------------*/
-
-#define _AWE_DEBUG_MODE			0x00
-#define _AWE_REVERB_MODE		0x01
-#define _AWE_CHORUS_MODE		0x02
-#define _AWE_REMOVE_LAST_SAMPLES	0x03
-#define _AWE_INITIALIZE_CHIP		0x04
-#define _AWE_SEND_EFFECT		0x05
-#define _AWE_TERMINATE_CHANNEL		0x06
-#define _AWE_TERMINATE_ALL		0x07
-#define _AWE_INITIAL_VOLUME		0x08
-#define _AWE_INITIAL_ATTEN	_AWE_INITIAL_VOLUME
-#define _AWE_RESET_CHANNEL		0x09
-#define _AWE_CHANNEL_MODE		0x0a
-#define _AWE_DRUM_CHANNELS		0x0b
-#define _AWE_MISC_MODE			0x0c
-#define _AWE_RELEASE_ALL		0x0d
-#define _AWE_NOTEOFF_ALL		0x0e
-#define _AWE_CHN_PRESSURE		0x0f
-/*#define _AWE_GET_CURRENT_MODE		0x10*/
-#define _AWE_EQUALIZER			0x11
-/*#define _AWE_GET_MISC_MODE		0x12*/
-/*#define _AWE_GET_FONTINFO		0x13*/
-
-#define _AWE_MODE_FLAG			0x80
-#define _AWE_COOKED_FLAG		0x40	/* not supported */
-#define _AWE_MODE_VALUE_MASK		0x3F
-
-/*----------------------------------------------------------------*/
-
-#define _AWE_SET_CMD(p,dev,voice,cmd,p1,p2) \
-{((char*)(p))[0] = SEQ_PRIVATE;\
- ((char*)(p))[1] = dev;\
- ((char*)(p))[2] = _AWE_MODE_FLAG|(cmd);\
- ((char*)(p))[3] = voice;\
- ((unsigned short*)(p))[2] = p1;\
- ((unsigned short*)(p))[3] = p2;}
-
-/* buffered access */
-#define _AWE_CMD(dev, voice, cmd, p1, p2) \
-{_SEQ_NEEDBUF(8);\
- _AWE_SET_CMD(_seqbuf + _seqbufptr, dev, voice, cmd, p1, p2);\
- _SEQ_ADVBUF(8);}
-
-/* direct access */
-#define _AWE_CMD_NOW(seqfd,dev,voice,cmd,p1,p2) \
-{struct seq_event_rec tmp;\
- _AWE_SET_CMD(&tmp, dev, voice, cmd, p1, p2);\
- ioctl(seqfd, SNDCTL_SEQ_OUTOFBAND, &tmp);}
-
-/*----------------------------------------------------------------*/
-
-/* set debugging mode */
-#define AWE_DEBUG_MODE(dev,p1)	_AWE_CMD(dev, 0, _AWE_DEBUG_MODE, p1, 0)
-/* set reverb mode; from 0 to 7 */
-#define AWE_REVERB_MODE(dev,p1)	_AWE_CMD(dev, 0, _AWE_REVERB_MODE, p1, 0)
-/* set chorus mode; from 0 to 7 */
-#define AWE_CHORUS_MODE(dev,p1)	_AWE_CMD(dev, 0, _AWE_CHORUS_MODE, p1, 0)
-
-/* reset channel */
-#define AWE_RESET_CHANNEL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 0, 0)
-#define AWE_RESET_CONTROL(dev,ch) _AWE_CMD(dev, ch, _AWE_RESET_CHANNEL, 1, 0)
-
-/* send an effect to all layers */
-#define AWE_SEND_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,type,value)
-#define AWE_ADD_EFFECT(dev,voice,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x80),value)
-#define AWE_UNSET_EFFECT(dev,voice,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((type)|0x40),0)
-/* send an effect to a layer */
-#define AWE_SEND_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)),value)
-#define AWE_ADD_LAYER_EFFECT(dev,voice,layer,type,value) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x80),value)
-#define AWE_UNSET_LAYER_EFFECT(dev,voice,layer,type) _AWE_CMD(dev,voice,_AWE_SEND_EFFECT,((layer+1)<<8|(type)|0x40),0)
-
-/* terminate sound on the channel/voice */
-#define AWE_TERMINATE_CHANNEL(dev,voice) _AWE_CMD(dev,voice,_AWE_TERMINATE_CHANNEL,0,0)
-/* terminate all sounds */
-#define AWE_TERMINATE_ALL(dev) _AWE_CMD(dev, 0, _AWE_TERMINATE_ALL, 0, 0)
-/* release all sounds (w/o sustain effect) */
-#define AWE_RELEASE_ALL(dev) _AWE_CMD(dev, 0, _AWE_RELEASE_ALL, 0, 0)
-/* note off all sounds (w sustain effect) */
-#define AWE_NOTEOFF_ALL(dev) _AWE_CMD(dev, 0, _AWE_NOTEOFF_ALL, 0, 0)
-
-/* set initial attenuation */
-#define AWE_INITIAL_VOLUME(dev,atten) _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 0)
-#define AWE_INITIAL_ATTEN  AWE_INITIAL_VOLUME
-/* relative attenuation */
-#define AWE_SET_ATTEN(dev,atten)  _AWE_CMD(dev, 0, _AWE_INITIAL_VOLUME, atten, 1)
-
-/* set channel playing mode; mode=0/1/2 */
-#define AWE_SET_CHANNEL_MODE(dev,mode) _AWE_CMD(dev, 0, _AWE_CHANNEL_MODE, mode, 0)
-#define AWE_PLAY_INDIRECT	0	/* indirect voice mode (default) */
-#define AWE_PLAY_MULTI		1	/* multi note voice mode */
-#define AWE_PLAY_DIRECT		2	/* direct single voice mode */
-#define AWE_PLAY_MULTI2		3	/* sequencer2 mode; used internally */
-
-/* set drum channel mask; channels is 32bit long value */
-#define AWE_DRUM_CHANNELS(dev,channels) _AWE_CMD(dev, 0, _AWE_DRUM_CHANNELS, ((channels) & 0xffff), ((channels) >> 16))
-
-/* set bass and treble control; values are from 0 to 11 */
-#define AWE_EQUALIZER(dev,bass,treble) _AWE_CMD(dev, 0, _AWE_EQUALIZER, bass, treble)
-
-/* remove last loaded samples */
-#define AWE_REMOVE_LAST_SAMPLES(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_REMOVE_LAST_SAMPLES, 0, 0)
-/* initialize emu8000 chip */
-#define AWE_INITIALIZE_CHIP(seqfd,dev) _AWE_CMD_NOW(seqfd, dev, 0, _AWE_INITIALIZE_CHIP, 0, 0)
-
-/* set miscellaneous modes; meta command */
-#define AWE_MISC_MODE(dev,mode,value) _AWE_CMD(dev, 0, _AWE_MISC_MODE, mode, value)
-/* exclusive sound off; 1=off */
-#define AWE_EXCLUSIVE_SOUND(dev,mode) AWE_MISC_MODE(dev,AWE_MD_EXCLUSIVE_SOUND,mode)
-/* default GUS bank number */
-#define AWE_SET_GUS_BANK(dev,bank) AWE_MISC_MODE(dev,AWE_MD_GUS_BANK,bank)
-/* change panning position in realtime; 0=don't 1=do */
-#define AWE_REALTIME_PAN(dev,mode) AWE_MISC_MODE(dev,AWE_MD_REALTIME_PAN,mode)
-
-/* extended pressure controls; not portable with other sound drivers */
-#define AWE_KEY_PRESSURE(dev,ch,note,vel) SEQ_START_NOTE(dev,ch,(note)+128,vel)
-#define AWE_CHN_PRESSURE(dev,ch,vel) _AWE_CMD(dev,ch,_AWE_CHN_PRESSURE,vel,0)
-
-/*----------------------------------------------------------------*/
-
-/* reverb mode parameters */
-#define	AWE_REVERB_ROOM1	0
-#define AWE_REVERB_ROOM2	1
-#define	AWE_REVERB_ROOM3	2
-#define	AWE_REVERB_HALL1	3
-#define	AWE_REVERB_HALL2	4
-#define	AWE_REVERB_PLATE	5
-#define	AWE_REVERB_DELAY	6
-#define	AWE_REVERB_PANNINGDELAY 7
-#define AWE_REVERB_PREDEFINED	8
-/* user can define reverb modes up to 32 */
-#define AWE_REVERB_NUMBERS	32
-
-typedef struct awe_reverb_fx_rec {
-	unsigned short parms[28];
-} awe_reverb_fx_rec;
-
-/*----------------------------------------------------------------*/
-
-/* chorus mode parameters */
-#define AWE_CHORUS_1		0
-#define	AWE_CHORUS_2		1
-#define	AWE_CHORUS_3		2
-#define	AWE_CHORUS_4		3
-#define	AWE_CHORUS_FEEDBACK	4
-#define	AWE_CHORUS_FLANGER	5
-#define	AWE_CHORUS_SHORTDELAY	6
-#define	AWE_CHORUS_SHORTDELAY2	7
-#define AWE_CHORUS_PREDEFINED	8
-/* user can define chorus modes up to 32 */
-#define AWE_CHORUS_NUMBERS	32
-
-typedef struct awe_chorus_fx_rec {
-	unsigned short feedback;	/* feedback level (0xE600-0xE6FF) */
-	unsigned short delay_offset;	/* delay (0-0x0DA3) [1/44100 sec] */
-	unsigned short lfo_depth;	/* LFO depth (0xBC00-0xBCFF) */
-	unsigned int delay;	/* right delay (0-0xFFFFFFFF) [1/256/44100 sec] */
-	unsigned int lfo_freq;		/* LFO freq LFO freq (0-0xFFFFFFFF) */
-} awe_chorus_fx_rec;
-
-/*----------------------------------------------------------------*/
-
-/* misc mode types */
-enum {
-/* 0*/	AWE_MD_EXCLUSIVE_OFF,	/* obsolete */
-/* 1*/	AWE_MD_EXCLUSIVE_ON,	/* obsolete */
-/* 2*/	AWE_MD_VERSION,		/* read only */
-/* 3*/	AWE_MD_EXCLUSIVE_SOUND,	/* ignored */
-/* 4*/	AWE_MD_REALTIME_PAN,	/* 0/1: do realtime pan change (default=1) */
-/* 5*/	AWE_MD_GUS_BANK,	/* bank number for GUS patches (default=0) */
-/* 6*/	AWE_MD_KEEP_EFFECT,	/* 0/1: keep effect values, (default=0) */
-/* 7*/	AWE_MD_ZERO_ATTEN,	/* attenuation of max volume (default=32) */
-/* 8*/	AWE_MD_CHN_PRIOR,	/* 0/1: set MIDI channel priority mode (default=1) */
-/* 9*/	AWE_MD_MOD_SENSE,	/* integer: modwheel sensitivity (def=18) */
-/*10*/	AWE_MD_DEF_PRESET,	/* integer: default preset number (def=0) */
-/*11*/	AWE_MD_DEF_BANK,	/* integer: default bank number (def=0) */
-/*12*/	AWE_MD_DEF_DRUM,	/* integer: default drumset number (def=0) */
-/*13*/	AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */
-	AWE_MD_END,
-};
-
-/*----------------------------------------------------------------*/
-
-/* effect parameters */
-enum {
-
-/* modulation envelope parameters */
-/* 0*/	AWE_FX_ENV1_DELAY,	/* WORD: ENVVAL */
-/* 1*/	AWE_FX_ENV1_ATTACK,	/* BYTE: up ATKHLD */
-/* 2*/	AWE_FX_ENV1_HOLD,	/* BYTE: lw ATKHLD */
-/* 3*/	AWE_FX_ENV1_DECAY,	/* BYTE: lw DCYSUS */
-/* 4*/	AWE_FX_ENV1_RELEASE,	/* BYTE: lw DCYSUS */
-/* 5*/	AWE_FX_ENV1_SUSTAIN,	/* BYTE: up DCYSUS */
-/* 6*/	AWE_FX_ENV1_PITCH,	/* BYTE: up PEFE */
-/* 7*/	AWE_FX_ENV1_CUTOFF,	/* BYTE: lw PEFE */
-
-/* volume envelope parameters */
-/* 8*/	AWE_FX_ENV2_DELAY,	/* WORD: ENVVOL */
-/* 9*/	AWE_FX_ENV2_ATTACK,	/* BYTE: up ATKHLDV */
-/*10*/	AWE_FX_ENV2_HOLD,	/* BYTE: lw ATKHLDV */
-/*11*/	AWE_FX_ENV2_DECAY,	/* BYTE: lw DCYSUSV */
-/*12*/	AWE_FX_ENV2_RELEASE,	/* BYTE: lw DCYSUSV */
-/*13*/	AWE_FX_ENV2_SUSTAIN,	/* BYTE: up DCYSUSV */
-	
-/* LFO1 (tremolo & vibrato) parameters */
-/*14*/	AWE_FX_LFO1_DELAY,	/* WORD: LFO1VAL */
-/*15*/	AWE_FX_LFO1_FREQ,	/* BYTE: lo TREMFRQ */
-/*16*/	AWE_FX_LFO1_VOLUME,	/* BYTE: up TREMFRQ */
-/*17*/	AWE_FX_LFO1_PITCH,	/* BYTE: up FMMOD */
-/*18*/	AWE_FX_LFO1_CUTOFF,	/* BYTE: lo FMMOD */
-
-/* LFO2 (vibrato) parameters */
-/*19*/	AWE_FX_LFO2_DELAY,	/* WORD: LFO2VAL */
-/*20*/	AWE_FX_LFO2_FREQ,	/* BYTE: lo FM2FRQ2 */
-/*21*/	AWE_FX_LFO2_PITCH,	/* BYTE: up FM2FRQ2 */
-
-/* Other overall effect parameters */
-/*22*/	AWE_FX_INIT_PITCH,	/* SHORT: pitch offset */
-/*23*/	AWE_FX_CHORUS,		/* BYTE: chorus effects send (0-255) */
-/*24*/	AWE_FX_REVERB,		/* BYTE: reverb effects send (0-255) */
-/*25*/	AWE_FX_CUTOFF,		/* BYTE: up IFATN */
-/*26*/	AWE_FX_FILTERQ,		/* BYTE: up CCCA */
-
-/* Sample / loop offset changes */
-/*27*/	AWE_FX_SAMPLE_START,	/* SHORT: offset */
-/*28*/	AWE_FX_LOOP_START,	/* SHORT: offset */
-/*29*/	AWE_FX_LOOP_END,	/* SHORT: offset */
-/*30*/	AWE_FX_COARSE_SAMPLE_START,	/* SHORT: upper word offset */
-/*31*/	AWE_FX_COARSE_LOOP_START,	/* SHORT: upper word offset */
-/*32*/	AWE_FX_COARSE_LOOP_END,		/* SHORT: upper word offset */
-/*33*/	AWE_FX_ATTEN,		/* BYTE: lo IFATN */
-
-	AWE_FX_END,
-};
-
-#endif /* AWE_VOICE_H */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/lowlevel/awe_wave.c linux/drivers/sound/lowlevel/awe_wave.c
--- v2.1.131/linux/drivers/sound/lowlevel/awe_wave.c	Thu Jul 16 18:09:26 1998
+++ linux/drivers/sound/lowlevel/awe_wave.c	Wed Dec 16 12:52:01 1998
@@ -1,10 +1,10 @@
 /*
  * sound/awe_wave.c
  *
- * The low level driver for the AWE32/Sound Blaster 32 wave table synth.
- *   version 0.4.2c; Oct. 7, 1997
+ * The low level driver for the AWE32/SB32/AWE64 wave table synth.
+ *   version 0.4.3; Nov. 1, 1998
  *
- * Copyright (C) 1996,1997 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -21,62 +21,27 @@
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+/* include initial header files and compatibility macros */
 #ifdef __FreeBSD__
-#  include <i386/isa/sound/awe_config.h>
+#  include <i386/isa/sound/awe_compat.h>
 #else
-#ifdef MODULE
-#include <linux/config.h>
-#include <linux/string.h>
-#include <linux/module.h>
-#  include "../soundmodule.h"
-#endif
-#  include "awe_config.h"
+#  include "awe_compat.h"
+#endif /* FreeBSD */
+#ifdef __linux__
+#  include <linux/config.h>
 #endif
 
 /*----------------------------------------------------------------*/
 
 #if defined(CONFIG_AWE32_SYNTH) || defined(CONFIG_AWE32_SYNTH_MODULE)
 
-#ifdef __FreeBSD__
-#  include <i386/isa/sound/awe_hw.h>
-#  include <i386/isa/sound/awe_version.h>
-#  include <i386/isa/sound/awe_voice.h>
-#else
-#  include "awe_hw.h"
-#  include "awe_version.h"
-#  include <linux/awe_voice.h>
-#endif
-
-#ifdef AWE_HAS_GUS_COMPATIBILITY
-/* include fine tuning table */
-#ifdef AWE_OBSOLETE_VOXWARE
-#  ifdef __FreeBSD__
-#    define SEQUENCER_C
-#    include <i386/isa/sound/tuning.h>
-#  else
-#    include "tuning.h"
-#  endif
-#else
-#  include "../tuning.h"
-#endif
-
-#ifdef linux
-#  include <linux/ultrasound.h>
-#elif defined(__FreeBSD__)
-#  include <machine/ultrasound.h>
-#endif
-
-#endif /* AWE_HAS_GUS_COMPATIBILITY */
-
-
 /*----------------------------------------------------------------
  * debug message
  *----------------------------------------------------------------*/
 
-static int debug_mode = 0;
 #ifdef AWE_DEBUG_ON
-#define DEBUG(LVL,XXX)	{if (debug_mode > LVL) { XXX; }}
-#define ERRMSG(XXX)	{if (debug_mode) { XXX; }}
+#define DEBUG(LVL,XXX)	{if (ctrls[AWE_MD_DEBUG_MODE] > LVL) { XXX; }}
+#define ERRMSG(XXX)	{if (ctrls[AWE_MD_DEBUG_MODE]) { XXX; }}
 #define FATALERR(XXX)	XXX
 #else
 #define DEBUG(LVL,XXX) /**/
@@ -97,7 +62,10 @@
 	int mem_ptr;		/* current word byte pointer */
 	int infos;
 	int samples;
-	/*char name[AWE_PATCH_NAME_LEN];*/
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	int shared;		/* shared index */
+	unsigned char name[AWE_PATCH_NAME_LEN];
+#endif
 } sf_list;
 
 /* bank record */
@@ -203,10 +171,12 @@
 	int apitch;		/* pitch parameter */
 	int avol;		/* volume parameter */
 	int apan;		/* panning parameter */
+	int acutoff;		/* cutoff parameter */
+	short aaux;		/* aux word */
 } voice_info;
 
 /* voice information */
-static voice_info *voices;
+static voice_info voices[AWE_MAX_VOICES];
 
 #define IS_NO_SOUND(v)	(voices[v].state & (AWE_ST_OFF|AWE_ST_RELEASED|AWE_ST_STANDBY|AWE_ST_SUSTAINED))
 #define IS_NO_EFFECT(v)	(voices[v].state != AWE_ST_ON)
@@ -215,7 +185,7 @@
 
 
 /* MIDI channel effects information (for hw control) */
-static awe_chan_info *channels;
+static awe_chan_info channels[AWE_MAX_CHANNELS];
 
 
 /*----------------------------------------------------------------
@@ -227,13 +197,23 @@
 #endif
 
 #ifndef AWE_DEFAULT_MEM_SIZE
-#define AWE_DEFAULT_MEM_SIZE	0	/* autodetect */
+#define AWE_DEFAULT_MEM_SIZE	-1	/* autodetect */
 #endif
 
+/* set variables */
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+/* replace awe_port variable with exported variable */
+#define awe_port	io
+#define BASEVAR_DECL	/**/
+#else
+#define BASEVAR_DECL	static
+#endif /* module */
+
 /* awe32 base address (overwritten at initialization) */
-static int awe_base = AWE_DEFAULT_BASE_ADDR;
+BASEVAR_DECL int awe_port = AWE_DEFAULT_BASE_ADDR;
 /* memory byte size */
-static int awe_mem_size = AWE_DEFAULT_MEM_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;
 
@@ -242,15 +222,13 @@
 
 static int patch_opened = 0;		/* sample already loaded? */
 
-static int reverb_mode = 4;		/* reverb mode */
-static int chorus_mode = 2;		/* chorus mode */
-static short init_atten = AWE_DEFAULT_ATTENUATION; /* 12dB below */
+static char atten_relative = FALSE;
+static short atten_offset = 0;
 
 static int awe_present = FALSE;		/* awe device present? */
 static int awe_busy = FALSE;		/* awe device opened? */
 
 static int my_dev = -1;			
-static int my_mixerdev = -1 ;
 
 #define DEFAULT_DRUM_FLAGS	((1 << 9) | (1 << 25))
 #define IS_DRUM_CHANNEL(c)	(drum_flags & (1 << (c)))
@@ -264,31 +242,6 @@
 
 static int current_alloc_time = 0;	/* voice allocation index for channel mode */
 
-static struct MiscModeDef {
-	int value;
-	int init_each_time;
-} misc_modes_default[AWE_MD_END] = {
-	{0,0}, {0,0}, /* <-- not used */
-	{AWE_VERSION_NUMBER, FALSE},
-	{TRUE, TRUE}, /* exclusive */
-	{TRUE, TRUE}, /* realpan */
-	{AWE_DEFAULT_BANK, TRUE}, /* gusbank */
-	{FALSE, TRUE}, /* keep effect */
-	{AWE_DEFAULT_ATTENUATION, FALSE}, /* zero_atten */
-	{FALSE, TRUE}, /* chn_prior */
-	{AWE_DEFAULT_MOD_SENSE, TRUE}, /* modwheel sense */
-	{AWE_DEFAULT_PRESET, TRUE}, /* def_preset */
-	{AWE_DEFAULT_BANK, TRUE}, /* def_bank */
-	{AWE_DEFAULT_DRUM, TRUE}, /* def_drum */
-	{FALSE, TRUE}, /* toggle_drum_bank */
-};
-
-static int misc_modes[AWE_MD_END];
-
-static int awe_bass_level = 5;
-static int awe_treble_level = 9;
-
-
 static struct synth_info awe_info = {
 	"AWE32 Synth",		/* name */
 	0,			/* device */
@@ -308,14 +261,15 @@
  * function prototypes
  *----------------------------------------------------------------*/
 
-#ifndef AWE_OBSOLETE_VOXWARE
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
 static int awe_check_port(void);
 static void awe_request_region(void);
 static void awe_release_region(void);
-#endif
+#endif /* linux & obsolete */
 
 static void awe_reset_samples(void);
 /* emu8000 chip i/o access */
+static void setup_ports(int p1, int p2, int p3);
 static void awe_poke(unsigned short cmd, unsigned short port, unsigned short data);
 static void awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data);
 static unsigned short awe_peek(unsigned short cmd, unsigned short port);
@@ -323,10 +277,12 @@
 static void awe_wait(unsigned short delay);
 
 /* initialize emu8000 chip */
+static int _attach_awe(void);
+static void _unload_awe(void);
 static void awe_initialize(void);
 
 /* set voice parameters */
-static void awe_init_misc_modes(int init_all);
+static void awe_init_ctrl_parms(int init_all);
 static void awe_init_voice_info(awe_voice_info *vp);
 static void awe_init_voice_parm(awe_voice_parm *pp);
 #ifdef AWE_HAS_GUS_COMPATIBILITY
@@ -337,7 +293,7 @@
 static int calc_parm_attack(int msec);
 static int calc_parm_decay(int msec);
 static int calc_parm_search(int msec, short *table);
-#endif
+#endif /* gus compat */
 
 /* turn on/off note */
 static void awe_note_on(int voice);
@@ -362,9 +318,13 @@
 static void awe_calc_pitch_from_freq(int voice, int freq);
 #endif
 static void awe_calc_volume(int voice);
+static void awe_update_volume(void);
+static void awe_change_master_volume(short val);
 static void awe_voice_init(int voice, int init_all);
 static void awe_channel_init(int ch, int init_all);
 static void awe_fx_init(int ch);
+static void awe_send_effect(int voice, int layer, int type, int val);
+static void awe_modwheel_change(int voice, int value);
 
 /* sequencer interface */
 static int awe_open(int dev, int mode);
@@ -389,6 +349,8 @@
 static int awe_alloc(int dev, int chn, int note, struct voice_alloc_info *alloc);
 static void awe_setup_voice(int dev, int voice, int chn);
 
+#define awe_key_pressure(dev,voice,key,press) awe_start_note(dev,voice,(key)+128,press)
+
 /* hardware controls */
 #ifdef AWE_HAS_GUS_COMPATIBILITY
 static void awe_hw_gus_control(int dev, int cmd, unsigned char *event);
@@ -417,6 +379,8 @@
 #ifdef AWE_HAS_GUS_COMPATIBILITY
 static int awe_load_guspatch(const char *addr, int offs, int size, int pmgr_flag);
 #endif
+/*static int awe_probe_info(awe_patch_info *patch, const char *addr, int count);*/
+static int awe_probe_data(awe_patch_info *patch, const char *addr, int count);
 static int check_patch_opened(int type, char *name);
 static int awe_write_wave_data(const char *addr, int offset, awe_sample_info *sp, int channels);
 static void add_sf_info(int rec);
@@ -426,6 +390,14 @@
 static void awe_remove_samples(int sf_id);
 static void rebuild_preset_list(void);
 static short awe_set_sample(awe_voice_info *vp);
+static int search_sample_index(int sf, int sample, int level);
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+static int is_identical_id(int id1, int id2);
+static int is_identical_name(unsigned char *name, int id);
+static int is_shared_sf(unsigned char *name);
+static int info_duplicated(awe_voice_list *rec);
+#endif /* allow sharing */
 
 /* lowlevel functions */
 static void awe_init_audio(void);
@@ -441,24 +413,83 @@
 static void awe_write_dram(unsigned short c);
 static int awe_detect_base(int addr);
 static int awe_detect(void);
-static int awe_check_dram(void);
+static void awe_check_dram(void);
 static int awe_load_chorus_fx(awe_patch_info *patch, const char *addr, int count);
 static void awe_set_chorus_mode(int mode);
+static void awe_update_chorus_mode(void);
 static int awe_load_reverb_fx(awe_patch_info *patch, const char *addr, int count);
 static void awe_set_reverb_mode(int mode);
+static void awe_update_reverb_mode(void);
 static void awe_equalizer(int bass, int treble);
+static void awe_update_equalizer(void);
+
 #ifdef CONFIG_AWE32_MIXER
-static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg);
+static void attach_mixer(void);
+static void unload_mixer(void);
+#endif
+
+#ifdef CONFIG_AWE32_MIDIEMU
+static void attach_midiemu(void);
+static void unload_midiemu(void);
 #endif
 
-/* define macros for compatibility */
+#define limitvalue(x, a, b) if ((x) < (a)) (x) = (a); else if ((x) > (b)) (x) = (b)
+
 #ifdef __FreeBSD__
-#  include <i386/isa/sound/awe_compat.h>
-#else
-#  include "awe_compat.h"
+/* FIXME */
+#define MALLOC_LOOP_DATA
+#define WAIT_BY_LOOP
 #endif
 
 /*----------------------------------------------------------------
+ * control parameters
+ *----------------------------------------------------------------*/
+
+
+#ifdef AWE_USE_NEW_VOLUME_CALC
+#define DEF_VOLUME_CALC	TRUE
+#else
+#define DEF_VOLUME_CALC	FALSE
+#endif /* new volume */
+
+#define DEF_ZERO_ATTEN		32	/* 12dB below */
+#define DEF_MOD_SENSE		18
+#define DEF_CHORUS_MODE		2
+#define DEF_REVERB_MODE		4
+#define DEF_BASS_LEVEL		5
+#define DEF_TREBLE_LEVEL	9
+
+static struct CtrlParmsDef {
+	int value;
+	int init_each_time;
+	void (*update)(void);
+} ctrl_parms[AWE_MD_END] = {
+	{0,0, NULL}, {0,0, NULL}, /* <-- not used */
+	{AWE_VERSION_NUMBER, FALSE, NULL},
+	{TRUE, FALSE, NULL}, /* exclusive */
+	{TRUE, FALSE, NULL}, /* realpan */
+	{AWE_DEFAULT_BANK, FALSE, NULL}, /* gusbank */
+	{FALSE, TRUE, NULL}, /* keep effect */
+	{DEF_ZERO_ATTEN, FALSE, awe_update_volume}, /* zero_atten */
+	{FALSE, FALSE, NULL}, /* chn_prior */
+	{DEF_MOD_SENSE, FALSE, NULL}, /* modwheel sense */
+	{AWE_DEFAULT_PRESET, FALSE, NULL}, /* def_preset */
+	{AWE_DEFAULT_BANK, FALSE, NULL}, /* def_bank */
+	{AWE_DEFAULT_DRUM, FALSE, NULL}, /* def_drum */
+	{FALSE, FALSE, NULL}, /* toggle_drum_bank */
+	{DEF_VOLUME_CALC, FALSE, awe_update_volume}, /* new_volume_calc */
+	{DEF_CHORUS_MODE, FALSE, awe_update_chorus_mode}, /* chorus mode */
+	{DEF_REVERB_MODE, FALSE, awe_update_reverb_mode}, /* reverb mode */
+	{DEF_BASS_LEVEL, FALSE, awe_update_equalizer}, /* bass level */
+	{DEF_TREBLE_LEVEL, FALSE, awe_update_equalizer}, /* treble level */
+	{0, FALSE, NULL},	/* debug mode */
+	{FALSE, FALSE, NULL}, /* pan exchange */
+};
+
+static int ctrls[AWE_MD_END];
+
+
+/*----------------------------------------------------------------
  * synth operation table
  *----------------------------------------------------------------*/
 
@@ -492,60 +523,34 @@
 	awe_setup_voice
 };
 
-#ifdef CONFIG_AWE32_MIXER
-static struct mixer_operations awe_mixer_operations = {
-#ifndef __FreeBSD__
-	"AWE32",
-#endif
-	"AWE32 Equalizer",
-	awe_mixer_ioctl,
-};
-#endif
-
 
 /*================================================================
- * attach / unload interface
+ * General attach / unload interface
  *================================================================*/
 
-#ifdef AWE_OBSOLETE_VOXWARE
-#define ATTACH_DECL	static
-#else
-#define ATTACH_DECL	/**/
-#endif
-
-ATTACH_DECL
-int attach_awe(void)
+static int _attach_awe(void)
 {
+	if (awe_present) return 0; /* for OSS38.. called twice? */
+
 	/* check presence of AWE32 card */
 	if (! awe_detect()) {
-		printk("AWE32: not detected\n");
+		printk(KERN_WARNING "AWE32: not detected\n");
 		return 0;
 	}
 
 	/* check AWE32 ports are available */
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
 	if (awe_check_port()) {
-		printk("AWE32: I/O area already used.\n");
+		printk(KERN_WARNING "AWE32: I/O area already used.\n");
 		return 0;
 	}
+#endif
 
 	/* set buffers to NULL */
-	voices = NULL;
-	channels = NULL;
 	sflists = NULL;
 	samples = NULL;
 	infos = NULL;
 
-	/* voice & channel info */
-	voices = (voice_info*)my_malloc(AWE_MAX_VOICES * sizeof(voice_info));
-	channels = (awe_chan_info*)my_malloc(AWE_MAX_CHANNELS * sizeof(awe_chan_info));
-
-	if (voices == NULL || channels == NULL) {
-		my_free(voices);
-		my_free(channels);
-		printk("AWE32: can't allocate sample tables\n");
-		return 0;
-	}
-
 	/* allocate sample tables */
 	INIT_TABLE(sflists, max_sfs, AWE_MAX_SF_LISTS, sf_list);
 	INIT_TABLE(samples, max_samples, AWE_MAX_SAMPLES, awe_sample_list);
@@ -553,8 +558,6 @@
 
 	my_dev = sound_alloc_synthdev();
 	if (my_dev == -1) {
-		my_free(voices);
-		my_free(channels);
 		printk(KERN_WARNING "AWE32 Error: too many synthesizers\n");
 		return 0;
 	}
@@ -564,13 +567,16 @@
 	synth_devs[my_dev] = &awe_operations;
 
 #ifdef CONFIG_AWE32_MIXER
-	if ((my_mixerdev=sound_alloc_mixerdev())!=-1) {
-		mixer_devs[my_mixerdev] = &awe_mixer_operations;
-	}
+	attach_mixer();
+#endif
+#ifdef CONFIG_AWE32_MIDIEMU
+	attach_midiemu();
 #endif
 
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
 	/* reserve I/O ports for awedrv */
 	awe_request_region();
+#endif
 
 	/* clear all samples */
 	awe_reset_samples();
@@ -580,21 +586,14 @@
 
 	sprintf(awe_info.name, "AWE32-%s (RAM%dk)",
 		AWEDRV_VERSION, awe_mem_size/1024);
-#ifdef __FreeBSD__
-	printk("awe0: <SoundBlaster EMU8000 MIDI (RAM%dk)>", awe_mem_size/1024);
-#elif defined(AWE_DEBUG_ON)
-	printk("%s\n", awe_info.name);
-#endif
-
-	/* set default values */
-	awe_init_misc_modes(TRUE);
-
-	/* set reverb & chorus modes */
-	awe_set_reverb_mode(reverb_mode);
-	awe_set_chorus_mode(chorus_mode);
+	printk("<SoundBlaster EMU8000 (RAM%dk)>\n", awe_mem_size/1024);
 
 	awe_present = TRUE;
 
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+	SOUND_LOCK;
+#endif
+
 	return 1;
 }
 
@@ -602,48 +601,168 @@
 #ifdef AWE_DYNAMIC_BUFFER
 static void free_tables(void)
 {
-	my_free(sflists);
+	if (sflists)
+		my_free(sflists);
 	sflists = NULL; max_sfs = 0;
-	my_free(samples);
+	if (samples)
+		my_free(samples);
 	samples = NULL; max_samples = 0;
-	my_free(infos);
+	if (infos)
+		my_free(infos);
 	infos = NULL; max_infos = 0;
 }
-#else
+
+static void *realloc_block(void *buf, int oldsize, int size)
+{
+	void *ptr;
+	if (oldsize == size)
+		return buf;
+	if ((ptr = my_malloc(size)) == NULL)
+		return NULL;
+	if (oldsize && size)
+		MEMCPY(ptr, buf, ((oldsize < size) ? oldsize : size) );
+	if (buf)
+		my_free(buf);
+	return ptr;
+}
+
+
+#else /* dynamic buffer */
+
 #define free_buffers() /**/
-#endif
 
+#endif /* dynamic_buffer */
 
-ATTACH_DECL
-void unload_awe(void)
+
+static void _unload_awe(void)
 {
 	if (awe_present) {
 		awe_reset_samples();
 		awe_release_region();
-		my_free(voices);
-		my_free(channels);
 		free_tables();
-		sound_unload_mixerdev(my_mixerdev);
+#ifdef CONFIG_AWE32_MIXER
+		unload_mixer();
+#endif
+#ifdef CONFIG_AWE32_MIDIEMU
+		unload_midiemu();
+#endif
 		sound_unload_synthdev(my_dev);
 		awe_present = FALSE;
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+		SOUND_LOCK_END;
+#endif
 	}
 }
 
 
+/*================================================================
+ * Linux interface
+ *================================================================*/
+
+#ifdef linux
+
 /*----------------------------------------------------------------
- * old type interface
+ * Linux PnP driver support
  *----------------------------------------------------------------*/
 
-#ifdef AWE_OBSOLETE_VOXWARE
+#ifdef CONFIG_PNP_DRV
 
-#ifdef __FreeBSD__
-long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
-#else
+#include <linux/pnp.h>
+
+BASEVAR_DECL int pnp = 1;	/* use PnP as default */
+
+#define AWE_NUM_CHIPS	3
+static unsigned int pnp_ids[AWE_NUM_CHIPS] = {
+	PNP_EISAID('C','T','L',0x0021),
+	PNP_EISAID('C','T','L',0x0022),
+	PNP_EISAID('C','T','L',0x0023),
+};
+static struct pnp_driver pnp_awe[AWE_NUM_CHIPS];
+static int awe_pnp_ok = 0;
+
+static void awe_pnp_config(struct pnp_device *d)
+{
+	struct pnp_resource *r;
+	int port[3];
+	int nio = 0;
+
+	port[0] = port[1] = port[2] = 0;
+	for (r = d->res; r != NULL; r = r->next) {
+		if (r->type == PNP_RES_IO) {
+			if (nio >= 0 && nio < 3)
+				port[nio] = r->start;
+			nio++;
+		}
+	}
+	setup_ports(port[0], port[1], port[2]);
+	DEBUG(0,printk("AWE32: PnP setup ports: %x:%x:%x\n", port[0], port[1], port[2]));
+}
+
+static int awe_pnp_event (struct pnp_device *d, struct pnp_drv_event *e)
+{
+	struct pnp_driver *drv = d->l.k.driver;
+
+	switch (e->type) {
+	case PNP_DRV_ALLOC:
+		drv->flags |= PNP_DRV_INUSE;
+		awe_pnp_ok = 1;
+		awe_pnp_config(d);
+		_attach_awe();
+		break;
+
+	case PNP_DRV_DISABLE:
+	case PNP_DRV_EMERGSTOP:
+		drv->flags &= ~PNP_DRV_INUSE;
+		awe_pnp_ok = 0;
+		_unload_awe();
+		break;
+
+	case PNP_DRV_CONFIG:
+		if (awe_busy) return 1; /* used now */
+		awe_release_region();
+		awe_pnp_config(d);
+		awe_request_region();
+		break;
+		
+	case PNP_DRV_RECONFIG:
+		break;
+	}
+	return 0;
+}
+
+static int awe_initpnp (void)
+{
+	int i;
+	for (i = 0; i < AWE_NUM_CHIPS; i++) {
+		pnp_awe[i].id.type = PNP_HDL_ISA;
+		pnp_awe[i].id.t.isa.id = pnp_ids[i];
+		pnp_awe[i].id.next = NULL;
+		pnp_awe[i].name = "Soundblaster AWE32/AWE64 PnP";
+		pnp_awe[i].event = awe_pnp_event;
+		pnp_register_driver(&pnp_awe[i], 1);
+	}
+	return 0;
+}
+
+static void awe_unload_pnp (void)
+{
+	int i;
+	for (i = 0; i < AWE_NUM_CHIPS; i++)
+		pnp_unregister_driver(&pnp_awe[i]);
+}
+#endif /* PnP support */
+
+/*----------------------------------------------------------------
+ * device / lowlevel (module) interface
+ *----------------------------------------------------------------*/
+
+#ifdef AWE_OBSOLETEL_VOXWARE
+
+/* old type interface */
 int attach_awe_obsolete(int mem_start, struct address_info *hw_config)
-#endif
 {
 	my_malloc_init(mem_start);
-	if (! attach_awe())
+	if (! _attach_awe())
 		return 0;
 	return my_malloc_memptr();
 }
@@ -654,8 +773,92 @@
 	/*return awe_detect();*/
 }
 
+#else /* !obsolete */
+
+/* new type interface */
+int attach_awe(void)
+{
+#ifdef CONFIG_PNP_DRV
+	if (pnp) {
+		awe_initpnp();
+		if (awe_pnp_ok)
+			return 0;
+	}
+#endif /* pnp */
+	_attach_awe();
+	return 0;
+}
+
+void unload_awe(void)
+{
+#ifdef CONFIG_PNP_DRV
+	if (pnp)
+		awe_unload_pnp();
+#endif /* pnp */
+	_unload_awe();
+}
+
+/* module interface */
+
+#if defined(AWE_MODULE_SUPPORT) && defined(MODULE)
+int init_module(void)
+{
+	return attach_awe();
+}
+
+void cleanup_module(void)
+{
+	unload_awe();
+}
+
+#ifdef MODULE_PARM
+MODULE_AUTHOR("Takashi Iwai <iwai@ww.uni-erlangen.de>");
+MODULE_DESCRIPTION("SB AWE32/64 WaveTable driver");
+MODULE_SUPPORTED_DEVICE("sound");
 #endif
 
+#endif /* module */
+
+#endif /* AWE_OBSOLETE_VOXWARE */
+
+#endif /* linux */
+
+
+/*================================================================
+ * FreeBSD interface
+ *================================================================*/
+
+#ifdef __FreeBSD__
+
+#ifdef AWE_OBSOLETE_VOXWARE
+long attach_awe_obsolete(long mem_start, struct address_info *hw_config)
+{
+	_attach_awe();
+	return 0;
+}
+
+int probe_awe_obsolete(struct address_info *hw_config)
+{
+	return 1;
+}
+
+#else /* !obsolete */
+
+/* new type interface */
+void attach_awe(struct address_info *hw_config)
+{
+	_attach_awe();
+}
+
+int probe_awe(struct address_info *hw_config)
+{
+	return 1;
+}
+
+#endif /* obsolete */
+
+#endif /* FreeBSD */
+
 
 /*================================================================
  * clear sample tables 
@@ -683,26 +886,44 @@
  *================================================================*/
 
 /* select a given AWE32 pointer */
+static int awe_ports[5];
+static int port_setuped = FALSE;
 static int awe_cur_cmd = -1;
 #define awe_set_cmd(cmd) \
-if (awe_cur_cmd != cmd) { OUTW(cmd, awe_base + 0x802); awe_cur_cmd = cmd; }
-#define awe_port(port)		(awe_base - 0x620 + port)
+if (awe_cur_cmd != cmd) { OUTW(cmd, awe_ports[Pointer]); awe_cur_cmd = cmd; }
+
+/* store values to i/o port array */
+static void setup_ports(int port1, int port2, int port3)
+{
+	awe_ports[0] = port1;
+	if (port2 == 0)
+		port2 = port1 + 0x400;
+	awe_ports[1] = port2;
+	awe_ports[2] = port2 + 2;
+	if (port3 == 0)
+		port3 = port1 + 0x800;
+	awe_ports[3] = port3;
+	awe_ports[4] = port3 + 2;
+
+	port_setuped = TRUE;
+}
 
 /* write 16bit data */
 INLINE static void
 awe_poke(unsigned short cmd, unsigned short port, unsigned short data)
 {
 	awe_set_cmd(cmd);
-	OUTW(data, awe_port(port));
+	OUTW(data, awe_ports[port]);
 }
 
 /* write 32bit data */
 INLINE static void
 awe_poke_dw(unsigned short cmd, unsigned short port, unsigned int data)
 {
+	unsigned short addr = awe_ports[port];
 	awe_set_cmd(cmd);
-	OUTW(data, awe_port(port));		/* write lower 16 bits */
-	OUTW(data >> 16, awe_port(port)+2);	/* write higher 16 bits */
+	OUTW(data, addr);		/* write lower 16 bits */
+	OUTW(data >> 16, addr + 2);	/* write higher 16 bits */
 }
 
 /* read 16bit data */
@@ -711,7 +932,7 @@
 {
 	unsigned short k;
 	awe_set_cmd(cmd);
-	k = inw(awe_port(port));
+	k = inw(awe_ports[port]);
 	return k;
 }
 
@@ -720,19 +941,21 @@
 awe_peek_dw(unsigned short cmd, unsigned short port)
 {
 	unsigned int k1, k2;
+	unsigned short addr = awe_ports[port];
 	awe_set_cmd(cmd);
-	k1 = inw(awe_port(port));
-	k2 = inw(awe_port(port)+2);
+	k1 = inw(addr);
+	k2 = inw(addr + 2);
 	k1 |= k2 << 16;
 	return k1;
 }
 
 /* wait delay number of AWE32 44100Hz clocks */
+#ifdef WAIT_BY_LOOP /* wait by loop -- that's not good.. */
 static void
 awe_wait(unsigned short delay)
 {
 	unsigned short clock, target;
-	unsigned short port = awe_port(AWE_WC_Port);
+	unsigned short port = awe_ports[AWE_WC_Port];
 	int counter;
   
 	/* sample counter */
@@ -749,6 +972,28 @@
 		if (counter > 65536)
 			break;
 }
+#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);
+}
+#endif /* wait by loop */
 
 /* write a word data */
 INLINE static void
@@ -758,38 +1003,41 @@
 }
 
 
-#ifndef AWE_OBSOLETE_VOXWARE
+#if defined(linux) && !defined(AWE_OBSOLETE_VOXWARE)
 
 /*================================================================
  * port check / request
- *  0x620-622, 0xA20-A22, 0xE20-E22
+ *  0x620-623, 0xA20-A23, 0xE20-E23
  *================================================================*/
 
 static int
 awe_check_port(void)
 {
-	return (check_region(awe_port(Data0), 4) ||
-		check_region(awe_port(Data1), 4) ||
-		check_region(awe_port(Data3), 4));
+	if (! port_setuped) return 0;
+	return (check_region(awe_ports[0], 4) ||
+		check_region(awe_ports[1], 4) ||
+		check_region(awe_ports[3], 4));
 }
 
 static void
 awe_request_region(void)
 {
-	request_region(awe_port(Data0), 4, "sound driver (AWE32)");
-	request_region(awe_port(Data1), 4, "sound driver (AWE32)");
-	request_region(awe_port(Data3), 4, "sound driver (AWE32)");
+	if (! port_setuped) return;
+	request_region(awe_ports[0], 4, "sound driver (AWE32)");
+	request_region(awe_ports[1], 4, "sound driver (AWE32)");
+	request_region(awe_ports[3], 4, "sound driver (AWE32)");
 }
 
 static void
 awe_release_region(void)
 {
-	release_region(awe_port(Data0), 4);
-	release_region(awe_port(Data1), 4);
-	release_region(awe_port(Data3), 4);
+	if (! port_setuped) return;
+	release_region(awe_ports[0], 4);
+	release_region(awe_ports[1], 4);
+	release_region(awe_ports[3], 4);
 }
 
-#endif /* !AWE_OBSOLETE_VOXWARE */
+#endif /* linux && !AWE_OBSOLETE_VOXWARE */
 
 
 /*================================================================
@@ -817,7 +1065,7 @@
 	awe_init_array();
 
 	/* check DRAM memory size */
-	awe_mem_size = awe_check_dram();
+	awe_check_dram();
 
 	/* initialize the FM section of the AWE32 */
 	awe_init_fm();
@@ -828,8 +1076,15 @@
 	/* enable audio */
 	awe_poke(AWE_HWCF3, 0x0004);
 
+	/* set default values */
+	awe_init_ctrl_parms(TRUE);
+
 	/* set equalizer */
-	awe_equalizer(5, 9);
+	awe_update_equalizer();
+
+	/* set reverb & chorus modes */
+	awe_update_reverb_mode();
+	awe_update_chorus_mode();
 }
 
 
@@ -1004,34 +1259,28 @@
 
 /* attack & decay/release time table (msec) */
 static short attack_time_tbl[128] = {
-32767, 11878, 5939, 3959, 2969, 2375, 1979, 1696, 1484, 1319, 1187, 1079, 989, 913, 848, 791, 742,
- 698, 659, 625, 593, 565, 539, 516, 494, 475, 456, 439, 424, 409, 395, 383, 371,
- 359, 344, 330, 316, 302, 290, 277, 266, 255, 244, 233, 224, 214, 205, 196, 188,
- 180, 173, 165, 158, 152, 145, 139, 133, 127, 122, 117, 112, 107, 103, 98, 94,
- 90, 86, 83, 79, 76, 73, 69, 67, 64, 61, 58, 56, 54, 51, 49, 47,
- 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 25, 24, 23,
- 22, 21, 20, 20, 19, 18, 17, 16, 16, 15, 14, 14, 13, 13, 12, 11,
- 11, 10, 10, 10, 9, 9, 8, 8, 8, 7, 7, 7, 6, 6, 0,
+32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
+707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
+361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
+180, 172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94,
+90, 86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47,
+45, 43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23,
+22, 21, 20, 19, 19, 18, 17, 16, 16, 15, 15, 14, 13, 13, 12, 12,
+11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
 };
 
 static short decay_time_tbl[128] = {
-32767, 32766, 4589, 4400, 4219, 4045, 3879, 3719, 3566, 3419, 3279, 3144, 3014, 2890, 2771, 2657,
- 2548, 2443, 2343, 2246, 2154, 2065, 1980, 1899, 1820, 1746, 1674, 1605, 1539, 1475, 1415, 1356,
- 1301, 1247, 1196, 1146, 1099, 1054, 1011, 969, 929, 891, 854, 819, 785, 753, 722, 692,
- 664, 636, 610, 585, 561, 538, 516, 494, 474, 455, 436, 418, 401, 384, 368, 353,
- 339, 325, 311, 298, 286, 274, 263, 252, 242, 232, 222, 213, 204, 196, 188, 180,
- 173, 166, 159, 152, 146, 140, 134, 129, 123, 118, 113, 109, 104, 100, 96, 92,
- 88, 84, 81, 77, 74, 71, 68, 65, 63, 60, 58, 55, 53, 51, 49, 47,
- 45, 43, 41, 39, 38, 36, 35, 33, 32, 30, 29, 28, 27, 26, 25, 24,
+32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
+2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
+1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
+691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377, 361,
+345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188, 180,
+172, 165, 158, 151, 145, 139, 133, 127, 122, 117, 112, 107, 102, 98, 94, 90,
+86, 82, 79, 75, 72, 69, 66, 63, 61, 58, 56, 53, 51, 49, 47, 45,
+43, 41, 39, 37, 36, 34, 33, 31, 30, 29, 28, 26, 25, 24, 23, 22,
 };
 
-/*
-static int
-calc_parm_delay(int msec)
-{
-	return (0x8000 - msec * 1000 / 725);
-}
-*/
+#define calc_parm_delay(msec) (0x8000 - (msec) * 1000 / 725);
 
 /* delay time = 0x8000 - msec/92 */
 static int
@@ -1095,6 +1344,7 @@
 
 #define PARM_BYTE	0
 #define PARM_WORD	1
+#define PARM_SIGN	2
 
 static struct PARM_DEFS {
 	int type;	/* byte or word */
@@ -1119,13 +1369,13 @@
 
 	{PARM_WORD, 0, 0x8000, NULL},	/* lfo1 delay */
 	{PARM_BYTE, 0, 0xff, awe_fx_tremfrq},	/* lfo1 freq */
-	{PARM_BYTE, 0, 0x7f, awe_fx_tremfrq},	/* lfo1 volume (positive only)*/
-	{PARM_BYTE, 0, 0x7f, awe_fx_fmmod},	/* lfo1 pitch (positive only)*/
-	{PARM_BYTE, 0, 0xff, awe_fx_fmmod},	/* lfo1 cutoff (positive only)*/
+	{PARM_SIGN, -128, 127, awe_fx_tremfrq},	/* lfo1 volume */
+	{PARM_SIGN, -128, 127, awe_fx_fmmod},	/* lfo1 pitch */
+	{PARM_BYTE, 0, 0xff, awe_fx_fmmod},	/* lfo1 cutoff */
 
 	{PARM_WORD, 0, 0x8000, NULL},	/* lfo2 delay */
 	{PARM_BYTE, 0, 0xff, awe_fx_fm2frq2},	/* lfo2 freq */
-	{PARM_BYTE, 0, 0x7f, awe_fx_fm2frq2},	/* lfo2 pitch (positive only)*/
+	{PARM_SIGN, -128, 127, awe_fx_fm2frq2},	/* lfo2 pitch */
 
 	{PARM_WORD, 0, 0xffff, awe_set_voice_pitch},	/* initial pitch */
 	{PARM_BYTE, 0, 0xff, NULL},	/* chorus */
@@ -1152,8 +1402,16 @@
 		effect = lay->val[type];
 	if (!on && (on = FX_ON(rec, type)) != 0)
 		effect = rec->val[type];
-	if (on == FX_FLAG_ADD)
-		effect += (int)value;
+	if (on == FX_FLAG_ADD) {
+		if (parm_defs[type].type == PARM_SIGN) {
+			if (value > 0x7f)
+				effect += (int)value - 0x100;
+			else
+				effect += (int)value;
+		} else {
+			effect += (int)value;
+		}
+	}
 	if (on) {
 		if (effect < parm_defs[type].low)
 			effect = parm_defs[type].low;
@@ -1221,12 +1479,20 @@
  * turn on/off sample
  *================================================================*/
 
+/* table for volume target calculation */
+static unsigned short voltarget[16] = { 
+   0xEAC0, 0XE0C8, 0XD740, 0XCE20, 0XC560, 0XBD08, 0XB500, 0XAD58,
+   0XA5F8, 0X9EF0, 0X9830, 0X91C0, 0X8B90, 0X85A8, 0X8000, 0X7A90
+};
+
 static void
 awe_note_on(int voice)
 {
 	unsigned int temp;
 	int addr;
+	int vtarget, ftarget, ptarget, pitch;
 	awe_voice_info *vp;
+	awe_voice_parm_block *parm;
 	FX_Rec *fx = &voices[voice].cinfo->fx;
 	FX_Rec *fx_lay = NULL;
 	if (voices[voice].layer < MAX_LAYERS)
@@ -1236,32 +1502,73 @@
 	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
 		return;
 
+	parm = (awe_voice_parm_block*)&vp->parm;
+
 	/* channel to be silent and idle */
 	awe_poke(AWE_DCYSUSV(voice), 0x0080);
-	awe_poke(AWE_VTFT(voice), 0);
-	awe_poke(AWE_CVCF(voice), 0);
+	awe_poke(AWE_VTFT(voice), 0x0000FFFF);
+	awe_poke(AWE_CVCF(voice), 0x0000FFFF);
 	awe_poke(AWE_PTRX(voice), 0);
 	awe_poke(AWE_CPF(voice), 0);
 
+	/* set pitch offset */
+	awe_set_pitch(voice, TRUE);
+
 	/* modulation & volume envelope */
-	awe_poke(AWE_ENVVAL(voice),
-		 FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, vp->parm.moddelay));
-	awe_poke(AWE_ATKHLD(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
-			 vp->parm.modatkhld));
+	if (parm->modatk >= 0x80 && parm->moddelay >= 0x8000) {
+		awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+		pitch = (parm->env1pit<<4) + voices[voice].apitch;
+		if (pitch > 0xffff) pitch = 0xffff;
+		/* calculate filter target */
+		ftarget = parm->cutoff + parm->env1fc;
+		limitvalue(ftarget, 0, 255);
+		ftarget <<= 8;
+	} else {
+		awe_poke(AWE_ENVVAL(voice),
+			 FX_WORD(fx, fx_lay, AWE_FX_ENV1_DELAY, parm->moddelay));
+		ftarget = parm->cutoff;
+		ftarget <<= 8;
+		pitch = voices[voice].apitch;
+	}
+
+	/* calcualte pitch target */
+	if (pitch != 0xffff) {
+		ptarget = 1 << (pitch >> 12);
+		if (pitch & 0x800) ptarget += (ptarget*0x102e)/0x2710;
+		if (pitch & 0x400) ptarget += (ptarget*0x764)/0x2710;
+		if (pitch & 0x200) ptarget += (ptarget*0x389)/0x2710;
+		ptarget += (ptarget>>1);
+		if (ptarget > 0xffff) ptarget = 0xffff;
+
+	} else ptarget = 0xffff;
+	if (parm->modatk >= 0x80)
+		awe_poke(AWE_ATKHLD(voice),
+			 FX_BYTE(fx, fx_lay, AWE_FX_ENV1_HOLD, parm->modhld) << 8 | 0x7f);
+	else
+		awe_poke(AWE_ATKHLD(voice),
+			 FX_COMB(fx, fx_lay, AWE_FX_ENV1_HOLD, AWE_FX_ENV1_ATTACK,
+				 vp->parm.modatkhld));
 	awe_poke(AWE_DCYSUS(voice),
 		 FX_COMB(fx, fx_lay, AWE_FX_ENV1_SUSTAIN, AWE_FX_ENV1_DECAY,
 			  vp->parm.moddcysus));
-	awe_poke(AWE_ENVVOL(voice),
-		 FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
-	awe_poke(AWE_ATKHLDV(voice),
-		 FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
+
+	if (parm->volatk >= 0x80 && parm->voldelay >= 0x8000) {
+		awe_poke(AWE_ENVVAL(voice), 0xBFFF);
+		vtarget = voltarget[voices[voice].avol%0x10]>>(voices[voice].avol>>4);
+	} else {
+		awe_poke(AWE_ENVVOL(voice),
+			 FX_WORD(fx, fx_lay, AWE_FX_ENV2_DELAY, vp->parm.voldelay));
+		vtarget = 0;
+	}
+	if (parm->volatk >= 0x80)
+		awe_poke(AWE_ATKHLDV(voice),
+			 FX_BYTE(fx, fx_lay, AWE_FX_ENV2_HOLD, parm->volhld) << 8 | 0x7f);
+	else
+		awe_poke(AWE_ATKHLDV(voice),
+			 FX_COMB(fx, fx_lay, AWE_FX_ENV2_HOLD, AWE_FX_ENV2_ATTACK,
 			 vp->parm.volatkhld));
 	/* decay/sustain parameter for volume envelope must be set at last */
 
-	/* pitch offset */
-	awe_set_pitch(voice, TRUE);
-
 	/* cutoff and volume */
 	awe_set_volume(voice, TRUE);
 
@@ -1303,9 +1610,13 @@
 	awe_poke_dw(AWE_CCCA(voice), temp);
 	DEBUG(4,printk("AWE32: [-- startaddr=%x/%x]\n", vp->start, addr));
 
+	/* clear unknown registers */
+	awe_poke_dw(AWE_00A0(voice), 0);
+	awe_poke_dw(AWE_0080(voice), 0);
+
 	/* reset volume */
-	awe_poke_dw(AWE_VTFT(voice), 0x0000FFFF);
-	awe_poke_dw(AWE_CVCF(voice), 0x0000FFFF);
+	awe_poke_dw(AWE_VTFT(voice), (vtarget<<16)|ftarget);
+	awe_poke_dw(AWE_CVCF(voice), (vtarget<<16)|ftarget);
 
 	/* turn on envelope */
 	awe_poke(AWE_DCYSUSV(voice),
@@ -1313,9 +1624,9 @@
 			  vp->parm.voldcysus));
 	/* set reverb */
 	temp = FX_BYTE(fx, fx_lay, AWE_FX_REVERB, vp->parm.reverb);
-	temp = (awe_peek_dw(AWE_PTRX(voice)) & 0xffff0000) | (temp<<8);
+	temp = (temp << 8) | (ptarget << 16) | voices[voice].aaux;
 	awe_poke_dw(AWE_PTRX(voice), temp);
-	awe_poke_dw(AWE_CPF(voice), 0x40000000);
+	awe_poke_dw(AWE_CPF(voice), ptarget << 16);
 
 	voices[voice].state = AWE_ST_ON;
 
@@ -1421,7 +1732,8 @@
 	if ((vp = voices[voice].sample) == NULL || vp->index < 0)
 		return;
 
-	tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF, vp->parm.cutoff);
+	tmp2 = FX_BYTE(fx, fx_lay, AWE_FX_CUTOFF,
+		       (unsigned char)voices[voice].acutoff);
 	tmp2 = (tmp2 << 8);
 	tmp2 |= FX_BYTE(fx, fx_lay, AWE_FX_ATTEN,
 			(unsigned char)voices[voice].avol);
@@ -1463,22 +1775,22 @@
 		if (vp->pan >= 0) /* 0-127 */
 			pos = (int)vp->pan * 2 - 128;
 		pos += voices[voice].cinfo->panning; /* -128 - 127 */
-		pos = 127 - pos;
-		if (pos < 0)
-			temp = 0;
-		else if (pos > 255)
-			temp = 255;
-		else
-			temp = pos;
+		temp = 127 - pos;
+	}
+	limitvalue(temp, 0, 255);
+	if (ctrls[AWE_MD_PAN_EXCHANGE]) {
+		temp = 255 - temp;
 	}
 	if (forced || temp != voices[voice].apan) {
+		voices[voice].apan = temp;
 		addr = vp->loopstart - 1;
 		addr += FX_OFFSET(fx, fx_lay, AWE_FX_LOOP_START,
 				  AWE_FX_COARSE_LOOP_START, vp->mode);
 		temp = (temp<<24) | (unsigned int)addr;
 		awe_poke_dw(AWE_PSST(voice), temp);
-		voices[voice].apan = temp;
 		DEBUG(4,printk("AWE32: [-- loopstart=%x/%x]\n", vp->loopstart, addr));
+		if (temp == 0) voices[voice].aaux = 0xff;
+		else voices[voice].aaux = (-temp)&0xff;
 	}
 }
 
@@ -1674,6 +1986,55 @@
 	2,2,2,2,2,1,1,1,1,1,0,0,0,0,0,0,
 };
 
+/* tables for volume->attenuation calculation */
+static unsigned char voltab1[128] = {
+   0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
+   0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
+   0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
+   0x19, 0x19, 0x18, 0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14,
+   0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10,
+   0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0d,
+   0x0d, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b,
+   0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09,
+   0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06,
+   0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x04,
+   0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02,
+   0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+   0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char voltab2[128] = {
+   0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
+   0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
+   0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
+   0x1a, 0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15,
+   0x14, 0x14, 0x13, 0x13, 0x13, 0x12, 0x12, 0x11, 0x11, 0x10,
+   0x10, 0x10, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d,
+   0x0d, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a,
+   0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08,
+   0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+   0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+   0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+   0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+   0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char expressiontab[128] = {
+   0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
+   0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
+   0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
+   0x24, 0x24, 0x23, 0x22, 0x21, 0x21, 0x20, 0x1f, 0x1e, 0x1e,
+   0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a, 0x1a, 0x19, 0x18, 0x18,
+   0x17, 0x17, 0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x13,
+   0x13, 0x12, 0x12, 0x11, 0x11, 0x11, 0x10, 0x10, 0x0f, 0x0f,
+   0x0f, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0c, 0x0c, 0x0c,
+   0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x09, 0x09,
+   0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+   0x06, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03,
+   0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+   0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
 static void
 awe_calc_volume(int voice)
 {
@@ -1693,23 +2054,70 @@
 			return;
 	}
 	
-	/* 0 - 127 */
-	vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127);
-	vol = vol * ap->amplitude / 127;
-
-	if (vol < 0) vol = 0;
-	if (vol > 127) vol = 127;
-
-	/* calc to attenuation */
-	vol = vol_table[vol];
-	vol = vol + (int)ap->attenuation + init_atten;
-	if (vol > 255) vol = 255;
+	if (ctrls[AWE_MD_NEW_VOLUME_CALC]) {
+		int main_vol = cp->main_vol * ap->amplitude / 127;
+		limitvalue(vp->velocity, 0, 127);
+		limitvalue(main_vol, 0, 127);
+		limitvalue(cp->expression_vol, 0, 127);
+
+		vol = voltab1[main_vol] + voltab2[vp->velocity];
+		vol = (vol * 8) / 3;
+		vol += ap->attenuation;
+		if (cp->expression_vol < 127)
+			vol += ((0x100 - vol) * expressiontab[cp->expression_vol])/128;
+		vol += atten_offset;
+		if (atten_relative)
+			vol += ctrls[AWE_MD_ZERO_ATTEN];
+		limitvalue(vol, 0, 255);
+		vp->avol = vol;
+		
+	} else {
+		/* 0 - 127 */
+		vol = (vp->velocity * cp->main_vol * cp->expression_vol) / (127*127);
+		vol = vol * ap->amplitude / 127;
 
-	vp->avol = vol;
+		if (vol < 0) vol = 0;
+		if (vol > 127) vol = 127;
+
+		/* calc to attenuation */
+		vol = vol_table[vol];
+		vol += (int)ap->attenuation;
+		vol += atten_offset;
+		if (atten_relative)
+			vol += ctrls[AWE_MD_ZERO_ATTEN];
+		if (vol > 255) vol = 255;
+
+		vp->avol = vol;
+	}
+	if (cp->bank !=  AWE_DRUM_BANK && ((awe_voice_parm_block*)(&ap->parm))->volatk < 0x7d) {
+		int atten;
+		if (vp->velocity < 70) atten = 70;
+		else atten = vp->velocity;
+		vp->acutoff = (atten * ap->parm.cutoff + 0xa0) >> 7;
+	} else {
+		vp->acutoff = ap->parm.cutoff;
+	}
 	DEBUG(3,printk("AWE32: [-- voice(%d) vol=%x]\n", voice, vol));
 }
 
-
+/* change master volume */
+static void
+awe_change_master_volume(short val)
+{
+	limitvalue(val, 0, 127);
+	atten_offset = vol_table[val];
+	atten_relative = TRUE;
+	awe_update_volume();
+}
+
+/* update volumes of all available channels */
+static void awe_update_volume(void)
+{
+	int i;
+	for (i = 0; i < awe_max_voices; i++)
+		awe_set_voice_vol(i, TRUE);
+}
+
 /* set sostenuto on */
 static void awe_sostenuto_on(int voice, int forced)
 {
@@ -1785,7 +2193,7 @@
 /* clear effects */
 static void awe_fx_init(int ch)
 {
-	if (SINGLE_LAYER_MODE() && !misc_modes[AWE_MD_KEEP_EFFECT]) {
+	if (SINGLE_LAYER_MODE() && !ctrls[AWE_MD_KEEP_EFFECT]) {
 		BZERO(&channels[ch].fx, sizeof(channels[ch].fx));
 		BZERO(&channels[ch].fx_layer, sizeof(&channels[ch].fx_layer));
 	}
@@ -1801,11 +2209,11 @@
 		cp->bender_range = 200; /* sense * 100 */
 		cp->main_vol = 127;
 		if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(ch)) {
-			cp->instr = misc_modes[AWE_MD_DEF_DRUM];
+			cp->instr = ctrls[AWE_MD_DEF_DRUM];
 			cp->bank = AWE_DRUM_BANK;
 		} else {
-			cp->instr = misc_modes[AWE_MD_DEF_PRESET];
-			cp->bank = misc_modes[AWE_MD_DEF_BANK];
+			cp->instr = ctrls[AWE_MD_DEF_PRESET];
+			cp->bank = ctrls[AWE_MD_DEF_BANK];
 		}
 		cp->vrec = -1;
 		cp->def_vrec = -1;
@@ -1816,7 +2224,7 @@
 	cp->chan_press = 0;
 	cp->sustained = 0;
 
-	if (! misc_modes[AWE_MD_KEEP_EFFECT]) {
+	if (! ctrls[AWE_MD_KEEP_EFFECT]) {
 		BZERO(&cp->fx, sizeof(cp->fx));
 		BZERO(&cp->fx_layer, sizeof(cp->fx_layer));
 	}
@@ -1861,8 +2269,9 @@
 	awe_busy = TRUE;
 
 	/* set default mode */
-	awe_init_misc_modes(FALSE);
-	init_atten = misc_modes[AWE_MD_ZERO_ATTEN];
+	awe_init_ctrl_parms(FALSE);
+	atten_relative = TRUE;
+	atten_offset = 0;
 	drum_flags = DEFAULT_DRUM_FLAGS;
 	playing_mode = AWE_PLAY_INDIRECT;
 
@@ -1889,12 +2298,12 @@
 /* set miscellaneous mode parameters
  */
 static void
-awe_init_misc_modes(int init_all)
+awe_init_ctrl_parms(int init_all)
 {
 	int i;
 	for (i = 0; i < AWE_MD_END; i++) {
-		if (init_all || misc_modes_default[i].init_each_time)
-			misc_modes[i] = misc_modes_default[i].value;
+		if (init_all || ctrl_parms[i].init_each_time)
+			ctrls[i] = ctrl_parms[i].value;
 	}
 }
 
@@ -2078,14 +2487,16 @@
 	}
 
 	/* if the same note still playing, stop it */
-	for (i = 0; i < awe_max_voices; i++)
-		if (voices[i].key == key) {
-			if (voices[i].state == AWE_ST_ON) {
-				awe_note_off(i);
-				awe_voice_init(i, FALSE);
-			} else if (voices[i].state == AWE_ST_STANDBY)
-				awe_voice_init(i, TRUE);
-		}
+	if (playing_mode != AWE_PLAY_DIRECT || ctrls[AWE_MD_EXCLUSIVE_SOUND]) {
+		for (i = 0; i < awe_max_voices; i++)
+			if (voices[i].key == key) {
+				if (voices[i].state == AWE_ST_ON) {
+					awe_note_off(i);
+					awe_voice_init(i, FALSE);
+				} else if (voices[i].state == AWE_ST_STANDBY)
+					awe_voice_init(i, TRUE);
+			}
+	}
 
 	/* allocate voices */
 	if (playing_mode == AWE_PLAY_DIRECT)
@@ -2114,6 +2525,7 @@
 {
 	int i;
 
+	limitvalue(preset, 0, AWE_MAX_PRESETS-1);
 	for (i = preset_table[preset]; i >= 0; i = infos[i].next_bank) {
 		if (infos[i].bank == bank)
 			return i;
@@ -2158,15 +2570,16 @@
 	cinfo->def_vrec = -1;
 	cinfo->vrec = awe_search_instr(def_bank, instr_no);
 	if (def_bank == AWE_DRUM_BANK)	/* search default drumset */
-		cinfo->def_vrec = awe_search_instr(def_bank, misc_modes[AWE_MD_DEF_DRUM]);
+		cinfo->def_vrec = awe_search_instr(def_bank, ctrls[AWE_MD_DEF_DRUM]);
 	else	/* search default preset */
-		cinfo->def_vrec = awe_search_instr(misc_modes[AWE_MD_DEF_BANK], instr_no);
+		cinfo->def_vrec = awe_search_instr(ctrls[AWE_MD_DEF_BANK], instr_no);
 
 	if (cinfo->vrec < 0 && cinfo->def_vrec < 0) {
 		DEBUG(1,printk("AWE32 Warning: can't find instrument %d\n", instr_no));
 	}
 
 	cinfo->instr = instr_no;
+	DEBUG(2,printk("AWE32: [program(%d) %d/%d]\n", voice, instr_no, def_bank));
 
 	return 0;
 }
@@ -2296,7 +2709,7 @@
 	}
 }
 
-#endif
+#endif /* gus_compat */
 
 
 /* AWE32 specific controls */
@@ -2306,8 +2719,6 @@
 	int voice;
 	unsigned short p1;
 	short p2;
-	awe_chan_info *cinfo;
-	FX_Rec *fx;
 	int i;
 
 	voice = event[3];
@@ -2322,19 +2733,20 @@
 
 	p1 = *(unsigned short *) &event[4];
 	p2 = *(short *) &event[6];
-	cinfo = &channels[voice];
 
 	switch (cmd) {
 	case _AWE_DEBUG_MODE:
-		debug_mode = p1;
-		printk("AWE32: debug mode = %d\n", debug_mode);
+		ctrls[AWE_MD_DEBUG_MODE] = p1;
+		printk("AWE32: debug mode = %d\n", ctrls[AWE_MD_DEBUG_MODE]);
 		break;
 	case _AWE_REVERB_MODE:
-		awe_set_reverb_mode(p1);
+		ctrls[AWE_MD_REVERB_MODE] = p1;
+		awe_update_reverb_mode();
 		break;
 
 	case _AWE_CHORUS_MODE:
-		awe_set_chorus_mode(p1);
+		ctrls[AWE_MD_CHORUS_MODE] = p1;
+		awe_update_chorus_mode();
 		break;
 		      
 	case _AWE_REMOVE_LAST_SAMPLES:
@@ -2348,30 +2760,13 @@
 		break;
 
 	case _AWE_SEND_EFFECT:
-		fx = &cinfo->fx;
-		i = FX_FLAG_SET;
+		i = -1;
 		if (p1 >= 0x100) {
-			int layer = (p1 >> 8);
-			if (layer >= 0 && layer < MAX_LAYERS)
-				fx = &cinfo->fx_layer[layer];
-			p1 &= 0xff;
-		}
-		if (p1 & 0x40) i = FX_FLAG_OFF;
-		if (p1 & 0x80) i = FX_FLAG_ADD;
-		p1 &= 0x3f;
-		if (p1 < AWE_FX_END) {
-			DEBUG(0,printk("AWE32: effects (%d) %d %d\n", voice, p1, p2));
-			if (i == FX_FLAG_SET)
-				FX_SET(fx, p1, p2);
-			else if (i == FX_FLAG_ADD)
-				FX_ADD(fx, p1, p2);
-			else
-				FX_UNSET(fx, p1);
-			if (i != FX_FLAG_OFF && parm_defs[p1].realtime) {
-				DEBUG(0,printk("AWE32: fx_realtime (%d)\n", voice));
-				awe_voice_change(voice, parm_defs[p1].realtime);
-			}
+			i = (p1 >> 8);
+			if (i < 0 || i >= MAX_LAYERS)
+				break;
 		}
+		awe_send_effect(voice, i, p1, p2);
 		break;
 
 	case _AWE_RESET_CHANNEL:
@@ -2395,22 +2790,14 @@
 
 	case _AWE_INITIAL_VOLUME:
 		DEBUG(0,printk("AWE32: init attenuation %d\n", p1));
-		if (p2 == 0) /* absolute value */
-			init_atten = (short)p1;
-		else /* relative value */
-			init_atten = misc_modes[AWE_MD_ZERO_ATTEN] + (short)p1;
-		if (init_atten < 0) init_atten = 0;
-		for (i = 0; i < awe_max_voices; i++)
-			awe_set_voice_vol(i, TRUE);
+		atten_relative = (char)p2;
+		atten_offset = (short)p1;
+		awe_update_volume();
 		break;
 
 	case _AWE_CHN_PRESSURE:
-		cinfo->chan_press = p1;
-		p1 = p1 * misc_modes[AWE_MD_MOD_SENSE] / 1200;
-		FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, p1);
-		awe_voice_change(voice, awe_fx_fmmod);
-		FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, p1);
-		awe_voice_change(voice, awe_fx_fm2frq2);
+		channels[voice].chan_press = p1;
+		awe_modwheel_change(voice, p1);
 		break;
 
 	case _AWE_CHANNEL_MODE:
@@ -2425,13 +2812,18 @@
 		break;
 
 	case _AWE_MISC_MODE:
-		DEBUG(0,printk("AWE32: misc mode = %d %d\n", p1, p2));
-		if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END)
-			misc_modes[p1] = p2;
+		DEBUG(0,printk("AWE32: ctrl parms = %d %d\n", p1, p2));
+		if (p1 > AWE_MD_VERSION && p1 < AWE_MD_END) {
+			ctrls[p1] = p2;
+			if (ctrl_parms[p1].update)
+				ctrl_parms[p1].update();
+		}
 		break;
 
 	case _AWE_EQUALIZER:
-		awe_equalizer((int)p1, (int)p2);
+		ctrls[AWE_MD_BASS_LEVEL] = p1;
+		ctrls[AWE_MD_TREBLE_LEVEL] = p2;
+		awe_update_equalizer();
 		break;
 
 	default:
@@ -2441,6 +2833,60 @@
 }
 
 
+/* change effects */
+static void
+awe_send_effect(int voice, int layer, int type, int val)
+{
+	awe_chan_info *cinfo;
+	FX_Rec *fx;
+	int mode;
+
+	cinfo = &channels[voice];
+	if (layer >= 0 && layer < MAX_LAYERS)
+		fx = &cinfo->fx_layer[layer];
+	else
+		fx = &cinfo->fx;
+
+	if (type & 0x40)
+		mode = FX_FLAG_OFF;
+	else if (type & 0x80)
+		mode = FX_FLAG_ADD;
+	else
+		mode = FX_FLAG_SET;
+	type &= 0x3f;
+
+	if (type >= 0 && type < AWE_FX_END) {
+		DEBUG(2,printk("AWE32: effects (%d) %d %d\n", voice, type, val));
+		if (mode == FX_FLAG_SET)
+			FX_SET(fx, type, val);
+		else if (mode == FX_FLAG_ADD)
+			FX_ADD(fx, type, val);
+		else
+			FX_UNSET(fx, type);
+		if (mode != FX_FLAG_OFF && parm_defs[type].realtime) {
+			DEBUG(2,printk("AWE32: fx_realtime (%d)\n", voice));
+			awe_voice_change(voice, parm_defs[type].realtime);
+		}
+	}
+}
+
+
+/* change modulation wheel; voice is already mapped on multi2 mode */
+static void
+awe_modwheel_change(int voice, int value)
+{
+	int i;
+	awe_chan_info *cinfo;
+
+	cinfo = &channels[voice];
+	i = value * ctrls[AWE_MD_MOD_SENSE] / 1200;
+	FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i);
+	awe_voice_change(voice, awe_fx_fmmod);
+	FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i);
+	awe_voice_change(voice, awe_fx_fm2frq2);
+}
+
+
 /* voice pressure change */
 static void
 awe_aftertouch(int dev, int voice, int pressure)
@@ -2458,7 +2904,7 @@
 		break;
 	case AWE_PLAY_MULTI2:
 		note = (voice_alloc->map[voice] & 0xff) - 1;
-		awe_start_note(dev, voice, note + 0x80, pressure);
+		awe_key_pressure(dev, voice, note + 0x80, pressure);
 		break;
 	}
 }
@@ -2468,7 +2914,6 @@
 static void
 awe_controller(int dev, int voice, int ctrl_num, int value)
 {
-	int i;
 	awe_chan_info *cinfo;
 
 	if (! voice_in_range(voice))
@@ -2486,7 +2931,7 @@
 	case CTL_BANK_SELECT: /* MIDI control #0 */
 		DEBUG(2,printk("AWE32: [bank(%d) %d]\n", voice, value));
 		if (MULTI_LAYER_MODE() && IS_DRUM_CHANNEL(voice) &&
-		    !misc_modes[AWE_MD_TOGGLE_DRUM_BANK])
+		    !ctrls[AWE_MD_TOGGLE_DRUM_BANK])
 			break;
 		cinfo->bank = value;
 		if (cinfo->bank == AWE_DRUM_BANK)
@@ -2498,11 +2943,7 @@
 
 	case CTL_MODWHEEL: /* MIDI control #1 */
 		DEBUG(2,printk("AWE32: [modwheel(%d) %d]\n", voice, value));
-		i = value * misc_modes[AWE_MD_MOD_SENSE] / 1200;
-		FX_ADD(&cinfo->fx, AWE_FX_LFO1_PITCH, i);
-		awe_voice_change(voice, awe_fx_fmmod);
-		FX_ADD(&cinfo->fx, AWE_FX_LFO2_PITCH, i);
-		awe_voice_change(voice, awe_fx_fm2frq2);
+		awe_modwheel_change(voice, value);
 		break;
 
 	case CTRL_PITCH_BENDER: /* SEQ1 V2 contorl */
@@ -2533,7 +2974,7 @@
 		DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, value));
 		/* (0-127) -> signed 8bit */
 		cinfo->panning = value * 2 - 128;
-		if (misc_modes[AWE_MD_REALTIME_PAN])
+		if (ctrls[AWE_MD_REALTIME_PAN])
 			awe_voice_change(voice, awe_set_pan);
 		break;
 
@@ -2557,14 +2998,12 @@
 		FX_SET(&cinfo->fx, AWE_FX_CHORUS, value * 2);
 		break;
 
-#ifdef AWE_ACCEPT_ALL_SOUNDS_CONTROLL
 	case 120:  /* all sounds off */
 		awe_note_off_all(FALSE);
 		break;
 	case 123:  /* all notes off */
 		awe_note_off_all(TRUE);
 		break;
-#endif
 
 	case CTL_SUSTAIN: /* MIDI control #64 */
 		cinfo->sustained = value;
@@ -2605,7 +3044,7 @@
 	cinfo = &channels[voice];
 	cinfo->panning = value;
 	DEBUG(2,printk("AWE32: [pan(%d) %d]\n", voice, cinfo->panning));
-	if (misc_modes[AWE_MD_REALTIME_PAN])
+	if (ctrls[AWE_MD_REALTIME_PAN])
 		awe_voice_change(voice, awe_set_pan);
 }
 
@@ -2714,6 +3153,12 @@
 	case AWE_MAP_PRESET:
 		rc = awe_load_map(&patch, addr, count);
 		break;
+	/* case AWE_PROBE_INFO:
+		rc = awe_probe_info(&patch, addr, count);
+		break;*/
+	case AWE_PROBE_DATA:
+		rc = awe_probe_data(&patch, addr, count);
+		break;
 	case AWE_LOAD_CHORUS_FX:
 		rc = awe_load_chorus_fx(&patch, addr, count);
 		break;
@@ -2740,45 +3185,135 @@
 	/* terminate sounds */
 	awe_reset(0);
 	if (current_sf_id >= max_sfs) {
+#ifndef AWE_DYNAMIC_BUFFER
+		return 1;
+#else
 		int newsize = max_sfs + AWE_MAX_SF_LISTS;
-		sf_list *newlist = my_realloc(sflists, sizeof(sf_list)*max_sfs,
-					      sizeof(sf_list)*newsize);
+		sf_list *newlist = realloc_block(sflists, sizeof(sf_list)*max_sfs,
+						 sizeof(sf_list)*newsize);
 		if (newlist == NULL)
 			return 1;
 		sflists = newlist;
 		max_sfs = newsize;
+#endif /* dynamic buffer */
 	}
 	rec = &sflists[current_sf_id];
 	rec->sf_id = current_sf_id + 1;
 	rec->type = type;
 	if (current_sf_id == 0 || (type & AWE_PAT_LOCKED) != 0)
 		locked_sf_id = current_sf_id + 1;
-	/*
-	if (name)
-		MEMCPY(rec->name, name, AWE_PATCH_NAME_LEN);
-	else
-		BZERO(rec->name, AWE_PATCH_NAME_LEN);
-	 */
 	rec->num_info = awe_free_info();
 	rec->num_sample = awe_free_sample();
 	rec->mem_ptr = awe_free_mem_ptr();
 	rec->infos = -1;
 	rec->samples = -1;
 
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	rec->shared = 0;
+	if (name)
+		memcpy(rec->name, name, AWE_PATCH_NAME_LEN);
+	else
+		strcpy(rec->name, "*TEMPORARY*");
+	if (current_sf_id > 0 && name && (type & AWE_PAT_SHARED) != 0) {
+		/* is the current font really a shared font? */
+		if (is_shared_sf(rec->name)) {
+			/* check if the shared font is already installed */
+			int i;
+			for (i = current_sf_id; i > 0; i--) {
+				if (is_identical_name(rec->name, i)) {
+					rec->shared = i;
+					break;
+				}
+			}
+		}
+	}
+#endif /* allow sharing */
+
 	current_sf_id++;
+
 	return 0;
 }
 
 
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+
+/* check if the given name is a valid shared name */
+#define ASC_TO_KEY(c) ((c) - 'A' + 1)
+static int is_shared_sf(unsigned char *name)
+{
+	static unsigned char id_head[6] = {
+		ASC_TO_KEY('A'), ASC_TO_KEY('W'), ASC_TO_KEY('E'),
+		AWE_MAJOR_VERSION,
+		AWE_MINOR_VERSION,
+		AWE_TINY_VERSION,
+	};
+	if (MEMCMP(name, id_head, 6) == 0)
+		return TRUE;
+	return FALSE;
+}
+
+/* check if the given name matches to the existing list */
+static int is_identical_name(unsigned char *name, int sf) 
+{
+	char *id = sflists[sf-1].name;
+	if (is_shared_sf(id) && MEMCMP(id, name, AWE_PATCH_NAME_LEN) == 0)
+		return TRUE;
+	return FALSE;
+}
+
+/* check if the given voice info exists */
+static int info_duplicated(awe_voice_list *rec)
+{
+	int j, sf_id;
+	sf_list *sf;
+
+	/* search for all sharing lists */
+	for (sf_id = rec->v.sf_id; sf_id > 0; sf_id = sf->shared) {
+		sf = &sflists[sf_id - 1];
+		for (j = sf->infos; j >= 0; j = infos[j].next) {
+			awe_voice_list *p = &infos[j];
+			if (p->type == V_ST_NORMAL &&
+			    p->bank == rec->bank &&
+			    p->instr == rec->instr &&
+			    p->v.low == rec->v.low &&
+			    p->v.high == rec->v.high &&
+			    p->v.sample == rec->v.sample)
+				return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+#endif /* AWE_ALLOW_SAMPLE_SHARING */
+
+
 /* open patch; create sf list and set opened flag */
 static int
 awe_open_patch(awe_patch_info *patch, const char *addr, int count)
 {
 	awe_open_parm parm;
+	int shared;
+
 	COPY_FROM_USER(&parm, addr, AWE_PATCH_INFO_SIZE, sizeof(parm));
-	if (awe_create_sf(parm.type, parm.name)) {
-		printk("AWE32: can't open: failed to alloc new list\n");
-		return RET_ERROR(ENOSPC);
+	shared = FALSE;
+
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	if (current_sf_id > 0 && (parm.type & AWE_PAT_SHARED) != 0) {
+		/* is the previous font the same font? */
+		if (is_identical_name(parm.name, current_sf_id)) {
+			/* then append to the previous */
+			shared = TRUE;
+			awe_reset(0);
+			if (parm.type & AWE_PAT_LOCKED)
+				locked_sf_id = current_sf_id;
+		}
+	}
+#endif /* allow sharing */
+	if (! shared) {
+		if (awe_create_sf(parm.type, parm.name)) {
+			printk("AWE32: can't open: failed to alloc new list\n");
+			return RET_ERROR(ENOSPC);
+		}
 	}
 	patch_opened = TRUE;
 	return current_sf_id;
@@ -2817,7 +3352,7 @@
 static int
 awe_unload_patch(awe_patch_info *patch, const char *addr, int count)
 {
-	if (current_sf_id > 0)
+	if (current_sf_id > 0 && current_sf_id > locked_sf_id)
 		awe_remove_samples(current_sf_id - 1);
 	return 0;
 }
@@ -2829,17 +3364,22 @@
 	awe_voice_list *newlist;
 	free_info = awe_free_info();
 	if (free_info + nvoices >= max_infos) {
+#ifndef AWE_DYNAMIC_BUFFER
+		printk("AWE32: can't alloc info table\n");
+		return RET_ERROR(ENOSPC);
+#else
 		do {
 			newsize = max_infos + AWE_MAX_INFOS;
 		} while (free_info + nvoices >= newsize);
-		newlist = my_realloc(infos, sizeof(awe_voice_list)*max_infos,
-				     sizeof(awe_voice_list)*newsize);
+		newlist = realloc_block(infos, sizeof(awe_voice_list)*max_infos,
+					sizeof(awe_voice_list)*newsize);
 		if (newlist == NULL) {
 			printk("AWE32: can't alloc info table\n");
 			return RET_ERROR(ENOSPC);
 		}
 		infos = newlist;
 		max_infos = newsize;
+#endif
 	}
 	return 0;
 }
@@ -2851,16 +3391,21 @@
 	awe_sample_list *newlist;
 	free_sample = awe_free_sample();
 	if (free_sample >= max_samples) {
+#ifndef AWE_DYNAMIC_BUFFER
+		printk("AWE32: can't alloc sample table\n");
+		return RET_ERROR(ENOSPC);
+#else
 		newsize = max_samples + AWE_MAX_SAMPLES;
-		newlist = my_realloc(samples,
-				     sizeof(awe_sample_list)*max_samples,
-				     sizeof(awe_sample_list)*newsize);
+		newlist = realloc_block(samples,
+					sizeof(awe_sample_list)*max_samples,
+					sizeof(awe_sample_list)*newsize);
 		if (newlist == NULL) {
 			printk("AWE32: can't alloc sample table\n");
 			return RET_ERROR(ENOSPC);
 		}
 		samples = newlist;
 		max_samples = newsize;
+#endif
 	}
 	return 0;
 }
@@ -2871,15 +3416,32 @@
 {
 	awe_voice_map map;
 	awe_voice_list *rec;
-	int free_info;
+	int p, free_info;
+
+	/* get the link info */
+	if (count < sizeof(map)) {
+		printk("AWE32 Error: invalid patch info length\n");
+		return RET_ERROR(EINVAL);
+	}
+	COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
+	
+	/* check if the identical mapping already exists */
+	p = awe_search_instr(map.map_bank, map.map_instr);
+	for (; p >= 0; p = infos[p].next_instr) {
+		if (p >= 0 && infos[p].type == V_ST_MAPPED &&
+		    infos[p].v.low == map.map_key &&
+		    infos[p].v.start == map.src_instr &&
+		    infos[p].v.end == map.src_bank &&
+		    infos[p].v.fixkey == map.src_key)
+			return 0; /* already present! */
+	}
 
 	if (check_patch_opened(AWE_PAT_TYPE_MAP, NULL) < 0)
 		return RET_ERROR(ENOSPC);
+
 	if (alloc_new_info(1) < 0)
 		return RET_ERROR(ENOSPC);
 
-	COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
-	
 	free_info = awe_free_info();
 	rec = &infos[free_info];
 	rec->bank = map.map_bank;
@@ -2901,6 +3463,54 @@
 	return 0;
 }
 
+#if 0
+/* probe preset in the current list -- nothing to be loaded */
+static int
+awe_probe_info(awe_patch_info *patch, const char *addr, int count)
+{
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	awe_voice_map map;
+	int p;
+
+	if (! patch_opened)
+		return RET_ERROR(EINVAL);
+
+	/* get the link info */
+	if (count < sizeof(map)) {
+		printk("AWE32 Error: invalid patch info length\n");
+		return RET_ERROR(EINVAL);
+	}
+	COPY_FROM_USER(&map, addr, AWE_PATCH_INFO_SIZE, sizeof(map));
+	
+	/* check if the identical mapping already exists */
+	p = awe_search_instr(map.src_bank, map.src_instr);
+	for (; p >= 0; p = infos[p].next_instr) {
+		if (p >= 0 && infos[p].type == V_ST_NORMAL &&
+		    is_identical_id(infos[p].v.sf_id, current_sf_id) &&
+		    infos[p].v.low <= map.src_key &&
+		    infos[p].v.high >= map.src_key)
+			return 0; /* already present! */
+	}
+#endif /* allow sharing */
+	return RET_ERROR(EINVAL);
+}
+#endif
+
+/* probe sample in the current list -- nothing to be loaded */
+static int
+awe_probe_data(awe_patch_info *patch, const char *addr, int count)
+{
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	if (! patch_opened)
+		return RET_ERROR(EINVAL);
+
+	/* search the specified sample by optarg */
+	if (search_sample_index(current_sf_id, patch->optarg, 0) >= 0)
+		return 0;
+#endif /* allow sharing */
+	return RET_ERROR(EINVAL);
+}
+
 /* load voice information data */
 static int
 awe_load_info(awe_patch_info *patch, const char *addr, int count)
@@ -2965,6 +3575,12 @@
 		COPY_FROM_USER(&infos[rec].v, addr, offset, AWE_VOICE_INFO_SIZE);
 		offset += AWE_VOICE_INFO_SIZE;
 		infos[rec].v.sf_id = current_sf_id;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+		if (sflists[current_sf_id-1].shared) {
+			if (info_duplicated(&infos[rec]))
+				continue;
+		}
+#endif /* allow sharing */
 		if (infos[rec].v.mode & AWE_MODE_INIT_PARM)
 			awe_init_voice_parm(&infos[rec].v.parm);
 		awe_set_sample(&infos[rec].v);
@@ -2975,32 +3591,45 @@
 	return 0;
 }
 
+
 /* load wave sample data */
 static int
 awe_load_data(awe_patch_info *patch, const char *addr, int count)
 {
 	int offset, size;
 	int rc, free_sample;
-	awe_sample_info *rec;
+	awe_sample_info tmprec, *rec;
 
 	if (check_patch_opened(AWE_PAT_TYPE_MISC, NULL) < 0)
 		return RET_ERROR(ENOSPC);
 
-	if (alloc_new_sample() < 0)
-		return RET_ERROR(ENOSPC);
-
-	free_sample = awe_free_sample();
-	rec = &samples[free_sample].v;
-
 	size = (count - AWE_SAMPLE_INFO_SIZE) / 2;
 	offset = AWE_PATCH_INFO_SIZE;
-	COPY_FROM_USER(rec, addr, offset, AWE_SAMPLE_INFO_SIZE);
+	COPY_FROM_USER(&tmprec, addr, offset, AWE_SAMPLE_INFO_SIZE);
 	offset += AWE_SAMPLE_INFO_SIZE;
-	if (size != rec->size) {
+	if (size != tmprec.size) {
 		printk("AWE32: load: sample size differed (%d != %d)\n",
-		       rec->size, size);
+		       tmprec.size, size);
 		return RET_ERROR(EINVAL);
 	}
+
+	if (search_sample_index(current_sf_id, tmprec.sample, 0) >= 0) {
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+		/* if shared sample, skip this data */
+		if (sflists[current_sf_id-1].type & AWE_PAT_SHARED)
+			return 0;
+#endif /* allow sharing */
+		DEBUG(1,printk("AWE32: sample data %d already present\n", tmprec.sample));
+		return RET_ERROR(EINVAL);
+	}
+
+	if (alloc_new_sample() < 0)
+		return RET_ERROR(ENOSPC);
+
+	free_sample = awe_free_sample();
+	rec = &samples[free_sample].v;
+	*rec = tmprec;
+
 	if (rec->size > 0)
 		if ((rc = awe_write_wave_data(addr, offset, rec, -1)) != 0)
 			return rc;
@@ -3078,7 +3707,7 @@
 static const char *readbuf_addr;
 static int readbuf_offs;
 static int readbuf_flags;
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
 static unsigned short *readbuf_loop;
 static int readbuf_loopstart, readbuf_loopend;
 #endif
@@ -3087,7 +3716,7 @@
 static int
 readbuf_init(const char *addr, int offset, awe_sample_info *sp)
 {
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
 	readbuf_loop = NULL;
 	readbuf_loopstart = sp->loopstart;
 	readbuf_loopend = sp->loopend;
@@ -3121,7 +3750,7 @@
 	}
 	if (readbuf_flags & AWE_SAMPLE_UNSIGNED)
 		c ^= 0x8000; /* unsigned -> signed */
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
 	/* write on cache for reverse loop */
 	if (readbuf_flags & (AWE_SAMPLE_BIDIR_LOOP|AWE_SAMPLE_REVERSE_LOOP)) {
 		if (pos >= readbuf_loopstart && pos < readbuf_loopend)
@@ -3131,7 +3760,7 @@
 	return c;
 }
 
-#ifdef __FreeBSD__
+#ifdef MALLOC_LOOP_DATA
 /* read from cache */
 static unsigned short
 readbuf_word_cache(int pos)
@@ -3184,7 +3813,7 @@
 	if (sp->mode_flags & AWE_SAMPLE_NO_BLANK)
 		truesize += BLANK_LOOP_SIZE;
 	if (awe_free_mem_ptr() + truesize >= awe_mem_size/2) {
-		printk("AWE32 Error: Sample memory full\n");
+		DEBUG(-1,printk("AWE32 Error: Sample memory full\n"));
 		return RET_ERROR(ENOSPC);
 	}
 
@@ -3418,7 +4047,7 @@
 	/* scale_freq, scale_factor, volume, and fractions not implemented */
 
 	/* append to the tail of the list */
-	infos[free_info].bank = misc_modes[AWE_MD_GUS_BANK];
+	infos[free_info].bank = ctrls[AWE_MD_GUS_BANK];
 	infos[free_info].instr = patch.instr_no;
 	infos[free_info].disabled = FALSE;
 	infos[free_info].type = V_ST_NORMAL;
@@ -3443,7 +4072,7 @@
 static void add_sf_info(int rec)
 {
 	int sf_id = infos[rec].v.sf_id;
-	if (sf_id == 0) return;
+	if (sf_id <= 0) return;
 	sf_id--;
 	if (sflists[sf_id].infos < 0)
 		sflists[sf_id].infos = rec;
@@ -3462,7 +4091,7 @@
 static void add_sf_sample(int rec)
 {
 	int sf_id = samples[rec].v.sf_id;
-	if (sf_id == 0) return;
+	if (sf_id <= 0) return;
 	sf_id--;
 	samples[rec].next = sflists[sf_id].samples;
 	sflists[sf_id].samples = rec;
@@ -3481,12 +4110,12 @@
 		for (cur = next; cur >= 0; cur = infos[cur].next_instr) {
 			if (infos[cur].v.low == low &&
 			    infos[cur].v.high == high &&
-			    infos[cur].v.sf_id != infos[rec].v.sf_id)
+			    ! is_identical_id(infos[cur].v.sf_id, infos[rec].v.sf_id))
 				*prevp = infos[cur].next_instr;
 			prevp = &infos[cur].next_instr;
 		}
 	} else {
-		if (infos[next].v.sf_id != infos[rec].v.sf_id)
+		if (! is_identical_id(infos[next].v.sf_id, infos[rec].v.sf_id))
 			infos[rec].next_instr = -1;
 	}
 }
@@ -3495,12 +4124,15 @@
 static void add_info_list(int rec)
 {
 	int *prevp, cur;
-	int instr = infos[rec].instr;
-	int bank = infos[rec].bank;
+	int instr;
+	int bank;
 
 	if (infos[rec].disabled)
 		return;
 
+	instr = infos[rec].instr;
+	bank = infos[rec].bank;
+	limitvalue(instr, 0, AWE_MAX_PRESETS-1);
 	prevp = &preset_table[instr];
 	cur = *prevp;
 	while (cur >= 0) {
@@ -3555,27 +4187,72 @@
 	}
 }
 
+/* compare the given sf_id pair */
+static int is_identical_id(int id1, int id2)
+{
+	if (id1 == id2)
+		return TRUE;
+	if (id1 <= 0 || id2 <= 0) /* this must not happen.. */
+		return FALSE;
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	{
+		/* compare with the sharing id */
+		int i;
+		if (id1 < id2) { /* make sure id1 > id2 */
+			int tmp; tmp = id1; id1 = id2; id2 = tmp;
+		}
+		for (i = sflists[id1-1].shared; i > 0; i = sflists[i-1].shared) {
+			if (i == id2)
+				return TRUE;
+		}
+	}
+#endif /* allow sharing */
+	return FALSE;
+}
+
+/* search the sample index matching with the given sample id */
+static int search_sample_index(int sf, int sample, int level)
+{
+	int i;
+
+	if (sf <= 0 || sf > current_sf_id)
+		return -1; /* this must not happen */
+
+	for (i = sflists[sf-1].samples; i >= 0; i = samples[i].next) {
+		if (samples[i].v.sample == sample)
+			return i;
+	}
+#ifdef AWE_ALLOW_SAMPLE_SHARING
+	if (sflists[sf-1].shared) { /* search recursively */
+		if (level > current_sf_id)
+			return -1; /* strange sharing loop.. quit */
+		return search_sample_index(sflists[sf-1].shared, sample, level + 1);
+	}
+#endif
+	return -1;
+}
+
 /* search the specified sample */
 static short
 awe_set_sample(awe_voice_info *vp)
 {
 	int i;
+
 	vp->index = -1;
-	for (i = sflists[vp->sf_id-1].samples; i >= 0; i = samples[i].next) {
-		if (samples[i].v.sample == vp->sample) {
-			/* set the actual sample offsets */
-			vp->start += samples[i].v.start;
-			vp->end += samples[i].v.end;
-			vp->loopstart += samples[i].v.loopstart;
-			vp->loopend += samples[i].v.loopend;
-			/* copy mode flags */
-			vp->mode = samples[i].v.mode_flags;
-			/* set index */
-			vp->index = i;
-			return i;
-		}
-	}
-	return -1;
+	if ((i = search_sample_index(vp->sf_id, vp->sample, 0)) < 0)
+		return -1;
+
+	/* set the actual sample offsets */
+	vp->start += samples[i].v.start;
+	vp->end += samples[i].v.end;
+	vp->loopstart += samples[i].v.loopstart;
+	vp->loopend += samples[i].v.loopend;
+	/* copy mode flags */
+	vp->mode = samples[i].v.mode_flags;
+	/* set index */
+	vp->index = i;
+
+	return i;
 }
 
 
@@ -3682,13 +4359,22 @@
 search_best_voice(int condition)
 {
 	int i, time, best;
+	int vtarget = 0xffff, min_vtarget = 0xffff;
+
 	best = -1;
 	time = current_alloc_time + 1;
 	for (i = 0; i < awe_max_voices; i++) {
-		if ((voices[i].state & condition) &&
-		    (best < 0 || voices[i].time < time)) {
+		if (! (voices[i].state & condition))
+			continue;
+#ifdef AWE_CHECK_VTARGET
+		/* get current volume */
+		vtarget = (awe_peek_dw(AWE_VTFT(i)) >> 16) & 0xffff;
+#endif
+		if (best < 0 || vtarget < min_vtarget ||
+		    (vtarget == min_vtarget && voices[i].time < time)) {
 			best = i;
 			time = voices[i].time;
+			min_vtarget = vtarget;
 		}
 	}
 	/* clear voice */
@@ -3718,8 +4404,7 @@
 	if ((best = search_best_voice(AWE_ST_SUSTAINED)) >= 0)
 		return best;
 
-#ifdef AWE_LOOKUP_MIDI_PRIORITY
-	if (MULTI_LAYER_MODE() && misc_modes[AWE_MD_CHN_PRIOR]) {
+	if (MULTI_LAYER_MODE() && ctrls[AWE_MD_CHN_PRIOR]) {
 		int ch = -1;
 		int time = current_alloc_time + 1;
 		int i;
@@ -3735,7 +4420,6 @@
 			}
 		}
 	}
-#endif
 	if (best < 0)
 		best = search_best_voice(~AWE_ST_MARK);
 
@@ -3823,10 +4507,35 @@
  * AWE32 mixer device control
  *================================================================*/
 
+static int awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg);
+
+static int my_mixerdev = -1;
+
+static struct mixer_operations awe_mixer_operations = {
+#ifndef __FreeBSD__
+	"AWE32",
+#endif
+	"AWE32 Equalizer",
+	awe_mixer_ioctl,
+};
+
+static void attach_mixer(void)
+{
+	if ((my_mixerdev = sound_alloc_mixerdev()) >= 0) {
+		mixer_devs[my_mixerdev] = &awe_mixer_operations;
+	}
+}
+
+static void unload_mixer(void)
+{
+	if (my_mixerdev >= 0)
+		sound_unload_mixerdev(my_mixerdev);
+}
+
 static int
 awe_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
-	int i, level;
+	int i, level, value;
 
 	if (((cmd >> 8) & 0xff) != 'M')
 		return RET_ERROR(EINVAL);
@@ -3838,38 +4547,43 @@
 	if (IO_WRITE_CHECK(cmd)) {
 		switch (cmd & 0xff) {
 		case SOUND_MIXER_BASS:
-			awe_bass_level = level * 12 / 100;
-			if (awe_bass_level >= 12)
-				awe_bass_level = 11;
-			awe_equalizer(awe_bass_level, awe_treble_level);
+			value = level * 12 / 100;
+			if (value >= 12)
+				value = 11;
+			ctrls[AWE_MD_BASS_LEVEL] = value;
+			awe_update_equalizer();
 			break;
 		case SOUND_MIXER_TREBLE:
-			awe_treble_level = level * 12 / 100;
-			if (awe_treble_level >= 12)
-				awe_treble_level = 11;
-			awe_equalizer(awe_bass_level, awe_treble_level);
+			value = level * 12 / 100;
+			if (value >= 12)
+				value = 11;
+			ctrls[AWE_MD_TREBLE_LEVEL] = value;
+			awe_update_equalizer();
 			break;
 		case SOUND_MIXER_VOLUME:
 			level = level * 127 / 100;
 			if (level >= 128) level = 127;
-			init_atten = vol_table[level];
-			for (i = 0; i < awe_max_voices; i++)
-				awe_set_voice_vol(i, TRUE);
+			atten_relative = FALSE;
+			atten_offset = vol_table[level];
+			awe_update_volume();
 			break;
 		}
 	}
 	switch (cmd & 0xff) {
 	case SOUND_MIXER_BASS:
-		level = awe_bass_level * 100 / 24;
+		level = ctrls[AWE_MD_BASS_LEVEL] * 100 / 24;
 		level = (level << 8) | level;
 		break;
 	case SOUND_MIXER_TREBLE:
-		level = awe_treble_level * 100 / 24;
+		level = ctrls[AWE_MD_TREBLE_LEVEL] * 100 / 24;
 		level = (level << 8) | level;
 		break;
 	case SOUND_MIXER_VOLUME:
+		value = atten_offset;
+		if (atten_relative)
+			value += ctrls[AWE_MD_ZERO_ATTEN];
 		for (i = 127; i > 0; i--) {
-			if (init_atten <= vol_table[i])
+			if (value <= vol_table[i])
 				break;
 		}
 		level = i * 100 / 127;
@@ -4168,8 +4882,10 @@
 		for (i = 0; i < AWE_NORMAL_VOICES; i++)
 			vidx[i] = i;
 	} else {
-		for (i = 0; i < channels; i++)
+		for (i = 0; i < channels; i++) {
 			vidx[i] = awe_clear_voice();
+			voices[vidx[i]].state = AWE_ST_MARK;
+		}
 	}
 
 	/* use all channels for DMA transfer */
@@ -4201,7 +4917,7 @@
 	if (awe_peek_dw(AWE_SMALW) & 0x80000000) {
 		for (i = 0; i < channels; i++) {
 			awe_poke_dw(AWE_CCCA(vidx[i]), 0);
-			voices[i].state = AWE_ST_OFF;
+			voices[vidx[i]].state = AWE_ST_OFF;
 		}
 		return RET_ERROR(ENOSPC);
 	}
@@ -4265,14 +4981,14 @@
 static int
 awe_detect_base(int addr)
 {
-	awe_base = addr;
+	setup_ports(addr, 0, 0);
 	if ((awe_peek(AWE_U1) & 0x000F) != 0x000C)
 		return 0;
 	if ((awe_peek(AWE_HWCF1) & 0x007E) != 0x0058)
 		return 0;
 	if ((awe_peek(AWE_HWCF2) & 0x0003) != 0x0003)
 		return 0;
-        DEBUG(0,printk("AWE32 found at %x\n", awe_base));
+        DEBUG(0,printk("AWE32 found at %x\n", addr));
 	return 1;
 }
 	
@@ -4280,13 +4996,22 @@
 awe_detect(void)
 {
 	int base;
-	if (awe_base == 0) {
+
+	if (port_setuped) /* already initialized by PnP */
+		return 1;
+
+	if (awe_port) /* use default i/o port value */
+		setup_ports(awe_port, 0, 0);
+	else { /* probe it */
 		for (base = 0x620; base <= 0x680; base += 0x20)
 			if (awe_detect_base(base))
 				return 1;
 		DEBUG(0,printk("AWE32 not found\n"));
 		return 0;
 	}
+	if (memsize >= 0) /* given by config file or module option */
+		awe_mem_size = memsize * 1024; /* convert to Kbytes */
+
 	return 1;
 }
 
@@ -4300,13 +5025,11 @@
 #define UNIQUE_ID2	0x4321
 #define UNIQUE_ID3	0xFFFF
 
-static int
+static void
 awe_check_dram(void)
 {
-	if (awe_mem_size > 0) {
-		awe_mem_size *= 1024; /* convert to Kbytes */
-		return awe_mem_size;
-	}
+	if (awe_mem_size >= 0) /* already initialized */
+		return;
 
 	awe_open_dram_for_check();
 
@@ -4318,7 +5041,7 @@
 	awe_poke(AWE_SMLD, UNIQUE_ID2);
 
 	while (awe_mem_size < AWE_MAX_DRAM_SIZE) {
-		awe_wait(2);
+		awe_wait(5);
 		/* read a data on the DRAM start address */
 		awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET);
 		awe_peek(AWE_SMLD); /* discard stale data  */
@@ -4326,7 +5049,7 @@
 			break;
 		if (awe_peek(AWE_SMLD) != UNIQUE_ID2)
 			break;
-		awe_mem_size += 32;  /* increment 32 Kbytes */
+		awe_mem_size += 512;  /* increment 512kbytes */
 		/* Write a unique data on the test address;
 		 * if the address is out of range, the data is written on
 		 * 0x200000(=AWE_DRAM_OFFSET).  Then the two id words are
@@ -4334,7 +5057,7 @@
 		 */
 		awe_poke_dw(AWE_SMALW, AWE_DRAM_OFFSET + awe_mem_size*512L);
 		awe_poke(AWE_SMLD, UNIQUE_ID3);
-		awe_wait(2);
+		awe_wait(5);
 		/* read a data on the just written DRAM address */
 		awe_poke_dw(AWE_SMALR, AWE_DRAM_OFFSET + awe_mem_size*512L);
 		awe_peek(AWE_SMLD); /* discard stale data  */
@@ -4347,7 +5070,6 @@
 
 	/* convert to Kbytes */
 	awe_mem_size *= 1024;
-	return awe_mem_size;
 }
 
 
@@ -4398,7 +5120,12 @@
 	awe_poke_dw(AWE_HWCF5, chorus_parm[effect].lfo_freq);
 	awe_poke_dw(AWE_HWCF6, 0x8000);
 	awe_poke_dw(AWE_HWCF7, 0x0000);
-	chorus_mode = effect;
+}
+
+static void
+awe_update_chorus_mode(void)
+{
+	awe_set_chorus_mode(ctrls[AWE_MD_CHORUS_MODE]);
 }
 
 /*----------------------------------------------------------------*/
@@ -4497,7 +5224,12 @@
 	for (i = 0; i < 28; i++)
 		awe_poke(reverb_cmds[i].cmd, reverb_cmds[i].port,
 			 reverb_parm[effect].parms[i]);
-	reverb_mode = effect;
+}
+
+static void
+awe_update_reverb_mode(void)
+{
+	awe_set_reverb_mode(ctrls[AWE_MD_REVERB_MODE]);
 }
 
 /*================================================================
@@ -4545,8 +5277,6 @@
 
 	if (bass < 0 || bass > 11 || treble < 0 || treble > 11)
 		return;
-	awe_bass_level = bass;
-	awe_treble_level = treble;
 	awe_poke(AWE_INIT4(0x01), bass_parm[bass][0]);
 	awe_poke(AWE_INIT4(0x11), bass_parm[bass][1]);
 	awe_poke(AWE_INIT3(0x11), treble_parm[treble][0]);
@@ -4562,20 +5292,968 @@
 	awe_poke(AWE_INIT4(0x1D), (unsigned short)(w + 0x8362));
 }
 
+static void awe_update_equalizer(void)
+{
+	awe_equalizer(ctrls[AWE_MD_BASS_LEVEL], ctrls[AWE_MD_TREBLE_LEVEL]);
+}
 
-#endif /* CONFIG_AWE32_SYNTH */
 
-#ifdef MODULE
-int init_module(void)
+#ifdef CONFIG_AWE32_MIDIEMU
+
+/*================================================================
+ * Emu8000 MIDI Emulation
+ *================================================================*/
+
+/*================================================================
+ * midi queue record
+ *================================================================*/
+
+/* queue type */
+enum { Q_NONE, Q_VARLEN, Q_READ, Q_SYSEX, };
+
+#define MAX_MIDIBUF	64
+
+/* midi status */
+typedef struct MidiStatus {
+	int queue;	/* queue type */
+	int qlen;	/* queue length */
+	int read;	/* chars read */
+	int status;	/* current status */
+	int chan;	/* current channel */
+	unsigned char buf[MAX_MIDIBUF];
+} MidiStatus;
+
+/* MIDI mode type */
+enum { MODE_GM, MODE_GS, MODE_XG, };
+
+/* NRPN / CC -> Emu8000 parameter converter */
+typedef struct {
+	int control;
+	int awe_effect;
+	unsigned short (*convert)(int val);
+} ConvTable;
+
+
+/*================================================================
+ * prototypes
+ *================================================================*/
+
+static int awe_midi_open(int dev, int mode, void (*input)(int,unsigned char), void (*output)(int));
+static void awe_midi_close(int dev);
+static int awe_midi_ioctl(int dev, unsigned cmd, caddr_t arg);
+static int awe_midi_outputc(int dev, unsigned char midi_byte);
+
+static void init_midi_status(MidiStatus *st);
+static void clear_rpn(void);
+static void get_midi_char(MidiStatus *st, int c);
+/*static void queue_varlen(MidiStatus *st, int c);*/
+static void special_event(MidiStatus *st, int c);
+static void queue_read(MidiStatus *st, int c);
+static void midi_note_on(MidiStatus *st);
+static void midi_note_off(MidiStatus *st);
+static void midi_key_pressure(MidiStatus *st);
+static void midi_channel_pressure(MidiStatus *st);
+static void midi_pitch_wheel(MidiStatus *st);
+static void midi_program_change(MidiStatus *st);
+static void midi_control_change(MidiStatus *st);
+static void midi_select_bank(MidiStatus *st, int val);
+static void midi_nrpn_event(MidiStatus *st);
+static void midi_rpn_event(MidiStatus *st);
+static void midi_detune(int chan, int coarse, int fine);
+static void midi_system_exclusive(MidiStatus *st);
+static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
+static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val);
+static int xg_control_change(MidiStatus *st, int cmd, int val);
+
+#define numberof(ary)	(sizeof(ary)/sizeof(ary[0]))
+
+
+/*================================================================
+ * OSS Midi device record
+ *================================================================*/
+
+static struct midi_operations awe_midi_operations =
 {
-	attach_awe();
-	SOUND_LOCK;
-	return 0;
+	{"AWE Midi Emu", 0, 0, SNDCARD_SB},
+	NULL /*&std_midi_synth*/,
+	{0}, /* input_info */
+	awe_midi_open, /*open*/
+	awe_midi_close, /*close*/
+	awe_midi_ioctl, /*ioctl*/
+	awe_midi_outputc, /*outputc*/
+	NULL /*start_read*/,
+	NULL /*end_read*/,
+	NULL, /* kick */
+	NULL, /* command */
+};
+
+static int my_mididev = -1;
+
+static void attach_midiemu(void)
+{
+	if ((my_mididev = sound_alloc_mididev()) < 0)
+		printk ("Sound: Too many midi devices detected\n");
+	else
+		midi_devs[my_mididev] = &awe_midi_operations;
 }
 
-void cleanup_module(void)
+static void unload_midiemu(void)
 {
-	unload_awe();
-	SOUND_LOCK_END;
+	if (my_mididev >= 0)
+		sound_unload_mididev(my_mididev);
 }
-#endif
+
+
+/*================================================================
+ * open/close midi device
+ *================================================================*/
+
+static int midi_opened = FALSE;
+
+static int midi_mode;
+static int coarsetune = 0, finetune = 0;
+
+static int xg_mapping = TRUE;
+static int xg_bankmode = 0;
+
+/* effect sensitivity */
+
+#define FX_CUTOFF	0
+#define FX_RESONANCE	1
+#define FX_ATTACK	2
+#define FX_RELEASE	3
+#define FX_VIBRATE	4
+#define FX_VIBDEPTH	5
+#define FX_VIBDELAY	6
+#define FX_NUMS		7
+
+#define DEF_FX_CUTOFF		170
+#define DEF_FX_RESONANCE	6
+#define DEF_FX_ATTACK		50
+#define DEF_FX_RELEASE		50
+#define DEF_FX_VIBRATE		30
+#define DEF_FX_VIBDEPTH		4
+#define DEF_FX_VIBDELAY		1500
+
+/* effect sense: */
+static int gs_sense[] = 
+{
+	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
+	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
+};
+static int xg_sense[] = 
+{
+	DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
+	DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
+};
+
+
+/* current status */
+static MidiStatus curst;
+
+
+static int
+awe_midi_open (int dev, int mode,
+	       void (*input)(int,unsigned char),
+	       void (*output)(int))
+{
+	if (midi_opened)
+		return -EBUSY;
+
+	midi_opened = TRUE;
+
+	midi_mode = MODE_GM;
+
+	curst.queue = Q_NONE;
+	curst.qlen = 0;
+	curst.read = 0;
+	curst.status = 0;
+	curst.chan = 0;
+	BZERO(curst.buf, sizeof(curst.buf));
+
+	init_midi_status(&curst);
+
+	return 0;
+}
+
+static void
+awe_midi_close (int dev)
+{
+	midi_opened = FALSE;
+}
+
+
+static int
+awe_midi_ioctl (int dev, unsigned cmd, caddr_t arg)
+{
+	return -EPERM;
+}
+
+static int
+awe_midi_outputc (int dev, unsigned char midi_byte)
+{
+	if (! midi_opened)
+		return 1;
+
+	/* force to change playing mode */
+	playing_mode = AWE_PLAY_MULTI;
+
+	get_midi_char(&curst, midi_byte);
+	return 1;
+}
+
+
+/*================================================================
+ * initialize
+ *================================================================*/
+
+static void init_midi_status(MidiStatus *st)
+{
+	clear_rpn();
+	coarsetune = 0;
+	finetune = 0;
+}
+
+
+/*================================================================
+ * RPN & NRPN
+ *================================================================*/
+
+#define MAX_MIDI_CHANNELS	16
+
+/* RPN & NRPN */
+static unsigned char nrpn[MAX_MIDI_CHANNELS];  /* current event is NRPN? */
+static int msb_bit;  /* current event is msb for RPN/NRPN */
+/* RPN & NRPN indeces */
+static unsigned char rpn_msb[MAX_MIDI_CHANNELS], rpn_lsb[MAX_MIDI_CHANNELS];
+/* RPN & NRPN values */
+static int rpn_val[MAX_MIDI_CHANNELS];
+
+static void clear_rpn(void)
+{
+	int i;
+	for (i = 0; i < MAX_MIDI_CHANNELS; i++) {
+		nrpn[i] = 0;
+		rpn_msb[i] = 127;
+		rpn_lsb[i] = 127;
+		rpn_val[i] = 0;
+	}
+	msb_bit = 0;
+}
+
+
+/*================================================================
+ * process midi queue
+ *================================================================*/
+
+/* status event types */
+typedef void (*StatusEvent)(MidiStatus *st);
+static struct StatusEventList {
+	StatusEvent process;
+	int qlen;
+} status_event[8] = {
+	{midi_note_off, 2},
+	{midi_note_on, 2},
+	{midi_key_pressure, 2},
+	{midi_control_change, 2},
+	{midi_program_change, 1},
+	{midi_channel_pressure, 1},
+	{midi_pitch_wheel, 2},
+	{NULL, 0},
+};
+
+
+/* read a char from fifo and process it */
+static void get_midi_char(MidiStatus *st, int c)
+{
+	if (c == 0xfe) {
+		/* ignore active sense */
+		st->queue = Q_NONE;
+		return;
+	}
+
+	switch (st->queue) {
+	/* case Q_VARLEN: queue_varlen(st, c); break;*/
+	case Q_READ:
+	case Q_SYSEX:
+		queue_read(st, c);
+		break;
+	case Q_NONE:
+		st->read = 0;
+		if ((c & 0xf0) == 0xf0) {
+			special_event(st, c);
+		} else if (c & 0x80) { /* status change */
+			st->status = (c >> 4) & 0x07;
+			st->chan = c & 0x0f;
+			st->queue = Q_READ;
+			st->qlen = status_event[st->status].qlen;
+			if (st->qlen == 0)
+				st->queue = Q_NONE;
+		}
+		break;
+	}
+}
+
+/* 0xfx events */
+static void special_event(MidiStatus *st, int c)
+{
+	switch (c) {
+	case 0xf0: /* system exclusive */
+		st->queue = Q_SYSEX;
+		st->qlen = 0;
+		break;
+	case 0xf1: /* MTC quarter frame */
+	case 0xf3: /* song select */
+		st->queue = Q_READ;
+		st->qlen = 1;
+		break;
+	case 0xf2: /* song position */
+		st->queue = Q_READ;
+		st->qlen = 2;
+		break;
+	}
+}
+
+#if 0
+/* read variable length value */
+static void queue_varlen(MidiStatus *st, int c)
+{
+	st->qlen += (c & 0x7f);
+	if (c & 0x80) {
+		st->qlen <<= 7;
+		return;
+	}
+	if (st->qlen <= 0) {
+		st->qlen = 0;
+		st->queue = Q_NONE;
+	}
+	st->queue = Q_READ;
+	st->read = 0;
+}
+#endif
+
+
+/* read a char */
+static void queue_read(MidiStatus *st, int c)
+{
+	if (st->read < MAX_MIDIBUF) {
+		if (st->queue != Q_SYSEX)
+			c &= 0x7f;
+		st->buf[st->read] = (unsigned char)c;
+	}
+	st->read++;
+	if (st->queue == Q_SYSEX && c == 0xf7) {
+		midi_system_exclusive(st);
+		st->queue = Q_NONE;
+	} else if (st->queue == Q_READ && st->read >= st->qlen) {
+		if (status_event[st->status].process)
+			status_event[st->status].process(st);
+		st->queue = Q_NONE;
+	}
+}
+
+
+/*================================================================
+ * status events
+ *================================================================*/
+
+/* note on */
+static void midi_note_on(MidiStatus *st)
+{
+	DEBUG(2,printk("midi: note_on (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
+	if (st->buf[1] == 0)
+		midi_note_off(st);
+	else
+		awe_start_note(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* note off */
+static void midi_note_off(MidiStatus *st)
+{
+	DEBUG(2,printk("midi: note_off (%d) %d %d\n", st->chan, st->buf[0], st->buf[1]));
+	awe_kill_note(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* key pressure change */
+static void midi_key_pressure(MidiStatus *st)
+{
+	awe_key_pressure(0, st->chan, st->buf[0], st->buf[1]);
+}
+
+/* channel pressure change */
+static void midi_channel_pressure(MidiStatus *st)
+{
+	channels[st->chan].chan_press = st->buf[0];
+	awe_modwheel_change(st->chan, st->buf[0]);
+}
+
+/* pitch wheel change */
+static void midi_pitch_wheel(MidiStatus *st)
+{
+	int val = (int)st->buf[1] * 128 + st->buf[0];
+	awe_bender(0, st->chan, val);
+}
+
+/* program change */
+static void midi_program_change(MidiStatus *st)
+{
+	int preset;
+	preset = st->buf[0];
+	if (midi_mode == MODE_GS && IS_DRUM_CHANNEL(st->chan) && preset == 127)
+		preset = 0;
+	else if (midi_mode == MODE_XG && xg_mapping && IS_DRUM_CHANNEL(st->chan))
+		preset += 64;
+
+	awe_set_instr(0, st->chan, preset);
+}
+
+#define send_effect(chan,type,val) awe_send_effect(chan,-1,type,val)
+#define add_effect(chan,type,val) awe_send_effect(chan,-1,(type)|0x80,val)
+#define unset_effect(chan,type) awe_send_effect(chan,-1,(type)|0x40,0)
+
+/* midi control change */
+static void midi_control_change(MidiStatus *st)
+{
+	int cmd = st->buf[0];
+	int val = st->buf[1];
+
+	DEBUG(2,printk("midi: control (%d) %d %d\n", st->chan, cmd, val));
+	if (midi_mode == MODE_XG) {
+		if (xg_control_change(st, cmd, val))
+			return;
+	}
+
+	/* controls #31 - #64 are LSB of #0 - #31 */
+	msb_bit = 1;
+	if (cmd >= 0x20 && cmd < 0x40) {
+		msb_bit = 0;
+		cmd -= 0x20;
+	}
+
+	switch (cmd) {
+	case CTL_SOFT_PEDAL:
+		if (val == 127)
+			add_effect(st->chan, AWE_FX_CUTOFF, -160);
+		else
+			unset_effect(st->chan, AWE_FX_CUTOFF);
+		break;
+
+	case CTL_BANK_SELECT:
+		midi_select_bank(st, val);
+		break;
+		
+	/* set RPN/NRPN parameter */
+	case CTL_REGIST_PARM_NUM_MSB:
+		nrpn[st->chan]=0; rpn_msb[st->chan]=val;
+		break;
+	case CTL_REGIST_PARM_NUM_LSB:
+		nrpn[st->chan]=0; rpn_lsb[st->chan]=val;
+		break;
+	case CTL_NONREG_PARM_NUM_MSB:
+		nrpn[st->chan]=1; rpn_msb[st->chan]=val;
+		break;
+	case CTL_NONREG_PARM_NUM_LSB:
+		nrpn[st->chan]=1; rpn_lsb[st->chan]=val;
+		break;
+
+	/* send RPN/NRPN entry */
+	case CTL_DATA_ENTRY:
+		if (msb_bit)
+			rpn_val[st->chan] = val * 128;
+		else
+			rpn_val[st->chan] |= val;
+		if (nrpn[st->chan])
+			midi_nrpn_event(st);
+		else
+			midi_rpn_event(st);
+		break;
+
+	/* increase/decrease data entry */
+	case CTL_DATA_INCREMENT:
+		rpn_val[st->chan]++;
+		midi_rpn_event(st);
+		break;
+	case CTL_DATA_DECREMENT:
+		rpn_val[st->chan]--;
+		midi_rpn_event(st);
+		break;
+
+	/* default */
+	default:
+		awe_controller(0, st->chan, cmd, val);
+		break;
+	}
+}
+
+/* tone bank change */
+static void midi_select_bank(MidiStatus *st, int val)
+{
+	if (midi_mode == MODE_XG && msb_bit) {
+		xg_bankmode = val;
+		/* XG MSB value; not normal bank selection */
+		switch (val) {
+		case 127: /* remap to drum channel */
+			awe_controller(0, st->chan, CTL_BANK_SELECT, 128);
+			break;
+		default: /* remap to normal channel */
+			awe_controller(0, st->chan, CTL_BANK_SELECT, val);
+			break;
+		}
+		return;
+	} else if (midi_mode == MODE_GS && !msb_bit)
+		/* ignore LSB bank in GS mode (used for mapping) */
+		return;
+
+	/* normal bank controls; accept both MSB and LSB */
+	if (! IS_DRUM_CHANNEL(st->chan)) {
+		if (midi_mode == MODE_XG) {
+			if (xg_bankmode) return;
+			if (val == 64 || val == 126)
+				val = 0;
+		} else if (midi_mode == MODE_GS && val == 127)
+			val = 0;
+		awe_controller(0, st->chan, CTL_BANK_SELECT, val);
+	}
+}
+
+
+/*================================================================
+ * RPN events
+ *================================================================*/
+
+static void midi_rpn_event(MidiStatus *st)
+{
+	int type;
+	type = (rpn_msb[st->chan]<<8) | rpn_lsb[st->chan];
+	switch (type) {
+	case 0x0000: /* Pitch bend sensitivity */
+		/* MSB only / 1 semitone per 128 */
+		if (msb_bit) {
+			channels[st->chan].bender_range = 
+				rpn_val[st->chan] * 100 / 128;
+		}
+		break;
+					
+	case 0x0001: /* fine tuning: */
+		/* MSB/LSB, 8192=center, 100/8192 cent step */
+		finetune = rpn_val[st->chan] - 8192;
+		midi_detune(st->chan, coarsetune, finetune);
+		break;
+
+	case 0x0002: /* coarse tuning */
+		/* MSB only / 8192=center, 1 semitone per 128 */
+		if (msb_bit) {
+			coarsetune = rpn_val[st->chan] - 8192;
+			midi_detune(st->chan, coarsetune, finetune);
+		}
+		break;
+
+	case 0x7F7F: /* "lock-in" RPN */
+		break;
+	}
+}
+
+
+/* tuning:
+ *   coarse = -8192 to 8192 (100 cent per 128)
+ *   fine = -8192 to 8192 (max=100cent)
+ */
+static void midi_detune(int chan, int coarse, int fine)
+{
+	/* 4096 = 1200 cents in AWE parameter */
+	int val;
+	val = coarse * 4096 / (12 * 128);
+	val += fine / 24;
+	if (val)
+		send_effect(chan, AWE_FX_INIT_PITCH, val);
+	else
+		unset_effect(chan, AWE_FX_INIT_PITCH);
+}
+
+
+/*================================================================
+ * system exclusive message
+ * GM/GS/XG macros are accepted
+ *================================================================*/
+
+static void midi_system_exclusive(MidiStatus *st)
+{
+	/* GM on */
+	static unsigned char gm_on_macro[] = {
+		0x7e,0x7f,0x09,0x01,
+	};
+	/* XG on */
+	static unsigned char xg_on_macro[] = {
+		0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
+	};
+	/* GS prefix
+	 * drum channel: XX=0x1?(channel), YY=0x15, ZZ=on/off
+	 * reverb mode: XX=0x01, YY=0x30, ZZ=0-7
+	 * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
+	 */
+	static unsigned char gs_pfx_macro[] = {
+		0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
+	};
+
+#if 0
+	/* SC88 system mode set
+	 * single module mode: XX=1
+	 * double module mode: XX=0
+	 */
+	static unsigned char gs_mode_macro[] = {
+		0x41,0x10,0x42,0x12,0x00,0x00,0x7F,/*ZZ*/
+	};
+	/* SC88 display macro: XX=01:bitmap, 00:text
+	 */
+	static unsigned char gs_disp_macro[] = {
+		0x41,0x10,0x45,0x12,0x10,/*XX,00*/
+	};
+#endif
+
+	/* GM on */
+	if (MEMCMP(st->buf, gm_on_macro, sizeof(gm_on_macro)) == 0) {
+		if (midi_mode != MODE_GS && midi_mode != MODE_XG)
+			midi_mode = MODE_GM;
+		init_midi_status(st);
+	}
+
+	/* GS macros */
+	else if (MEMCMP(st->buf, gs_pfx_macro, sizeof(gs_pfx_macro)) == 0) {
+		if (midi_mode != MODE_GS && midi_mode != MODE_XG)
+			midi_mode = MODE_GS;
+
+		if (st->buf[5] == 0x00 && st->buf[6] == 0x7f && st->buf[7] == 0x00) {
+			/* GS reset */
+			init_midi_status(st);
+		}
+
+		else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x15) {
+			/* drum pattern */
+			int p = st->buf[5] & 0x0f;
+			if (p == 0) p = 9;
+			else if (p < 10) p--;
+			if (st->buf[7] == 0)
+				DRUM_CHANNEL_OFF(p);
+			else
+				DRUM_CHANNEL_ON(p);
+
+		} else if ((st->buf[5] & 0xf0) == 0x10 && st->buf[6] == 0x21) {
+			/* program */
+			int p = st->buf[5] & 0x0f;
+			if (p == 0) p = 9;
+			else if (p < 10) p--;
+			if (! IS_DRUM_CHANNEL(p))
+				awe_set_instr(0, p, st->buf[7]);
+
+		} else if (st->buf[5] == 0x01 && st->buf[6] == 0x30) {
+			/* reverb mode */
+			awe_set_reverb_mode(st->buf[7]);
+
+		} else if (st->buf[5] == 0x01 && st->buf[6] == 0x38) {
+			/* chorus mode */
+			awe_set_chorus_mode(st->buf[7]);
+
+		} else if (st->buf[5] == 0x00 && st->buf[6] == 0x04) {
+			/* master volume */
+			awe_change_master_volume(st->buf[7]);
+
+		}
+	}
+
+	/* XG on */
+	else if (MEMCMP(st->buf, xg_on_macro, sizeof(xg_on_macro)) == 0) {
+		midi_mode = MODE_XG;
+		xg_mapping = TRUE;
+		xg_bankmode = 0;
+	}
+}
+
+
+/*================================================================
+ * convert NRPN/control values
+ *================================================================*/
+
+static int send_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
+{
+	int i, cval;
+	for (i = 0; i < num_tables; i++) {
+		if (table[i].control == type) {
+			cval = table[i].convert(val);
+			send_effect(st->chan, table[i].awe_effect, cval);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+static int add_converted_effect(ConvTable *table, int num_tables, MidiStatus *st, int type, int val)
+{
+	int i, cval;
+	for (i = 0; i < num_tables; i++) {
+		if (table[i].control == type) {
+			cval = table[i].convert(val);
+			add_effect(st->chan, table[i].awe_effect|0x80, cval);
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+
+/*----------------------------------------------------------------
+ * AWE32 NRPN effects
+ *----------------------------------------------------------------*/
+
+static unsigned short fx_delay(int val);
+static unsigned short fx_attack(int val);
+static unsigned short fx_hold(int val);
+static unsigned short fx_decay(int val);
+static unsigned short fx_the_value(int val);
+static unsigned short fx_twice_value(int val);
+static unsigned short fx_conv_pitch(int val);
+static unsigned short fx_conv_Q(int val);
+
+/* function for each NRPN */		/* [range]  units */
+#define fx_env1_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_env1_attack	fx_attack	/* [0,5940] 1msec */
+#define fx_env1_hold	fx_hold		/* [0,8191] 1msec */
+#define fx_env1_decay	fx_decay	/* [0,5940] 4msec */
+#define fx_env1_release	fx_decay	/* [0,5940] 4msec */
+#define fx_env1_sustain	fx_the_value	/* [0,127] 0.75dB */
+#define fx_env1_pitch	fx_the_value	/* [-127,127] 9.375cents */
+#define fx_env1_cutoff	fx_the_value	/* [-127,127] 56.25cents */
+
+#define fx_env2_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_env2_attack	fx_attack	/* [0,5940] 1msec */
+#define fx_env2_hold	fx_hold		/* [0,8191] 1msec */
+#define fx_env2_decay	fx_decay	/* [0,5940] 4msec */
+#define fx_env2_release	fx_decay	/* [0,5940] 4msec */
+#define fx_env2_sustain	fx_the_value	/* [0,127] 0.75dB */
+
+#define fx_lfo1_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_lfo1_freq	fx_twice_value	/* [0,127] 84mHz */
+#define fx_lfo1_volume	fx_twice_value	/* [0,127] 0.1875dB */
+#define fx_lfo1_pitch	fx_the_value	/* [-127,127] 9.375cents */
+#define fx_lfo1_cutoff	fx_twice_value	/* [-64,63] 56.25cents */
+
+#define fx_lfo2_delay	fx_delay	/* [0,5900] 4msec */
+#define fx_lfo2_freq	fx_twice_value	/* [0,127] 84mHz */
+#define fx_lfo2_pitch	fx_the_value	/* [-127,127] 9.375cents */
+
+#define fx_init_pitch	fx_conv_pitch	/* [-8192,8192] cents */
+#define fx_chorus	fx_the_value	/* [0,255] -- */
+#define fx_reverb	fx_the_value	/* [0,255] -- */
+#define fx_cutoff	fx_twice_value	/* [0,127] 62Hz */
+#define fx_filterQ	fx_conv_Q	/* [0,127] -- */
+
+static unsigned short fx_delay(int val)
+{
+	return (unsigned short)calc_parm_delay(val);
+}
+
+static unsigned short fx_attack(int val)
+{
+	return (unsigned short)calc_parm_attack(val);
+}
+
+static unsigned short fx_hold(int val)
+{
+	return (unsigned short)calc_parm_hold(val);
+}
+
+static unsigned short fx_decay(int val)
+{
+	return (unsigned short)calc_parm_decay(val);
+}
+
+static unsigned short fx_the_value(int val)
+{
+	return (unsigned short)(val & 0xff);
+}
+
+static unsigned short fx_twice_value(int val)
+{
+	return (unsigned short)((val * 2) & 0xff);
+}
+
+static unsigned short fx_conv_pitch(int val)
+{
+	return (short)(val * 4096 / 1200);
+}
+
+static unsigned short fx_conv_Q(int val)
+{
+	return (unsigned short)((val / 8) & 0xff);
+}
+
+
+static ConvTable awe_effects[] =
+{
+	{ 0, AWE_FX_LFO1_DELAY,	fx_lfo1_delay},
+	{ 1, AWE_FX_LFO1_FREQ,	fx_lfo1_freq},
+	{ 2, AWE_FX_LFO2_DELAY,	fx_lfo2_delay},
+	{ 3, AWE_FX_LFO2_FREQ,	fx_lfo2_freq},
+
+	{ 4, AWE_FX_ENV1_DELAY,	fx_env1_delay},
+	{ 5, AWE_FX_ENV1_ATTACK,fx_env1_attack},
+	{ 6, AWE_FX_ENV1_HOLD,	fx_env1_hold},
+	{ 7, AWE_FX_ENV1_DECAY,	fx_env1_decay},
+	{ 8, AWE_FX_ENV1_SUSTAIN,	fx_env1_sustain},
+	{ 9, AWE_FX_ENV1_RELEASE,	fx_env1_release},
+
+	{10, AWE_FX_ENV2_DELAY,	fx_env2_delay},
+	{11, AWE_FX_ENV2_ATTACK,	fx_env2_attack},
+	{12, AWE_FX_ENV2_HOLD,	fx_env2_hold},
+	{13, AWE_FX_ENV2_DECAY,	fx_env2_decay},
+	{14, AWE_FX_ENV2_SUSTAIN,	fx_env2_sustain},
+	{15, AWE_FX_ENV2_RELEASE,	fx_env2_release},
+
+	{16, AWE_FX_INIT_PITCH,	fx_init_pitch},
+	{17, AWE_FX_LFO1_PITCH,	fx_lfo1_pitch},
+	{18, AWE_FX_LFO2_PITCH,	fx_lfo2_pitch},
+	{19, AWE_FX_ENV1_PITCH,	fx_env1_pitch},
+	{20, AWE_FX_LFO1_VOLUME,	fx_lfo1_volume},
+	{21, AWE_FX_CUTOFF,		fx_cutoff},
+	{22, AWE_FX_FILTERQ,	fx_filterQ},
+	{23, AWE_FX_LFO1_CUTOFF,	fx_lfo1_cutoff},
+	{24, AWE_FX_ENV1_CUTOFF,	fx_env1_cutoff},
+	{25, AWE_FX_CHORUS,		fx_chorus},
+	{26, AWE_FX_REVERB,		fx_reverb},
+};
+
+static int num_awe_effects = numberof(awe_effects);
+
+
+/*----------------------------------------------------------------
+ * GS(SC88) NRPN effects; still experimental
+ *----------------------------------------------------------------*/
+
+/* cutoff: quarter semitone step, max=255 */
+static unsigned short gs_cutoff(int val)
+{
+	return (val - 64) * gs_sense[FX_CUTOFF] / 50;
+}
+
+/* resonance: 0 to 15(max) */
+static unsigned short gs_filterQ(int val)
+{
+	return (val - 64) * gs_sense[FX_RESONANCE] / 50;
+}
+
+/* attack: */
+static unsigned short gs_attack(int val)
+{
+	return -(val - 64) * gs_sense[FX_ATTACK] / 50;
+}
+
+/* decay: */
+static unsigned short gs_decay(int val)
+{
+	return -(val - 64) * gs_sense[FX_RELEASE] / 50;
+}
+
+/* release: */
+static unsigned short gs_release(int val)
+{
+	return -(val - 64) * gs_sense[FX_RELEASE] / 50;
+}
+
+/* vibrato freq: 0.042Hz step, max=255 */
+static unsigned short gs_vib_rate(int val)
+{
+	return (val - 64) * gs_sense[FX_VIBRATE] / 50;
+}
+
+/* vibrato depth: max=127, 1 octave */
+static unsigned short gs_vib_depth(int val)
+{
+	return (val - 64) * gs_sense[FX_VIBDEPTH] / 50;
+}
+
+/* vibrato delay: -0.725msec step */
+static unsigned short gs_vib_delay(int val)
+{
+	return -(val - 64) * gs_sense[FX_VIBDELAY] / 50;
+}
+
+static ConvTable gs_effects[] =
+{
+	{32, AWE_FX_CUTOFF,	gs_cutoff},
+	{33, AWE_FX_FILTERQ,	gs_filterQ},
+	{99, AWE_FX_ENV2_ATTACK, gs_attack},
+	{100, AWE_FX_ENV2_DECAY, gs_decay},
+	{102, AWE_FX_ENV2_RELEASE, gs_release},
+	{8, AWE_FX_LFO1_FREQ, gs_vib_rate},
+	{9, AWE_FX_LFO1_VOLUME, gs_vib_depth},
+	{10, AWE_FX_LFO1_DELAY, gs_vib_delay},
+};
+
+static int num_gs_effects = numberof(gs_effects);
+
+
+/*================================================================
+ * NRPN events: accept as AWE32/SC88 specific controls
+ *================================================================*/
+
+static void midi_nrpn_event(MidiStatus *st)
+{
+	if (rpn_msb[st->chan] == 127 && rpn_lsb[st->chan] <= 26) {
+		if (! msb_bit) /* both MSB/LSB necessary */
+			send_converted_effect(awe_effects, num_awe_effects,
+					      st, rpn_lsb[st->chan],
+					      rpn_val[st->chan] - 8192);
+	} else if (rpn_msb[st->chan] == 1) {
+		if (msb_bit) /* only MSB is valid */
+			add_converted_effect(gs_effects, num_gs_effects,
+					     st, rpn_lsb[st->chan],
+					     rpn_val[st->chan] / 128);
+	}
+}
+
+
+/*----------------------------------------------------------------
+ * XG control effects; still experimental
+ *----------------------------------------------------------------*/
+
+/* cutoff: quarter semitone step, max=255 */
+static unsigned short xg_cutoff(int val)
+{
+	return (val - 64) * xg_sense[FX_CUTOFF] / 64;
+}
+
+/* resonance: 0(open) to 15(most nasal) */
+static unsigned short xg_filterQ(int val)
+{
+	return (val - 64) * xg_sense[FX_RESONANCE] / 64;
+}
+
+/* attack: */
+static unsigned short xg_attack(int val)
+{
+	return -(val - 64) * xg_sense[FX_ATTACK] / 64;
+}
+
+/* release: */
+static unsigned short xg_release(int val)
+{
+	return -(val - 64) * xg_sense[FX_RELEASE] / 64;
+}
+
+static ConvTable xg_effects[] =
+{
+	{71, AWE_FX_CUTOFF,	xg_cutoff},
+	{74, AWE_FX_FILTERQ,	xg_filterQ},
+	{72, AWE_FX_ENV2_RELEASE, xg_release},
+	{73, AWE_FX_ENV2_ATTACK, xg_attack},
+};
+
+static int num_xg_effects = numberof(xg_effects);
+
+static int xg_control_change(MidiStatus *st, int cmd, int val)
+{
+	return add_converted_effect(xg_effects, num_xg_effects, st, cmd, val);
+}
+
+#endif /* CONFIG_AWE32_MIDIEMU */
+
+#endif /* CONFIG_AWE32_SYNTH */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/midibuf.c linux/drivers/sound/midibuf.c
--- v2.1.131/linux/drivers/sound/midibuf.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/midibuf.c	Wed Dec 16 12:52:01 1998
@@ -40,7 +40,7 @@
 
 struct midi_parms
 {
-	int prech_timeout;	/*
+	long prech_timeout;	/*
 				 * Timeout before the first ch
 				 */
 };
@@ -282,8 +282,14 @@
 		n = SPACE_AVAIL(midi_out_buf[dev]);
 
 		if (n == 0) {	/*
-				 * No space just now. We have to sleep
+				 * No space just now.
 				 */
+
+			if (file->f_flags & O_NONBLOCK) {
+				restore_flags(flags);
+				return -EAGAIN;
+			}
+
 			interruptible_sleep_on(&midi_sleeper[dev]);
 			if (signal_pending(current)) 
 			{
@@ -322,6 +328,10 @@
 	if (!DATA_AVAIL(midi_in_buf[dev])) {	/*
 						 * No data yet, wait
 						 */
+ 		if (file->f_flags & O_NONBLOCK) {
+ 			restore_flags(flags);
+ 			return -EAGAIN;
+ 		}
 		interruptible_sleep_on_timeout(&input_sleeper[dev],
 					       parms[dev].prech_timeout);
 
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/msnd.h linux/drivers/sound/msnd.h
--- v2.1.131/linux/drivers/sound/msnd.h	Fri Oct 23 22:01:22 1998
+++ linux/drivers/sound/msnd.h	Wed Dec 16 12:52:01 1998
@@ -24,13 +24,13 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd.h,v 1.32 1998/10/09 19:54:39 andrewtv Exp $
+ * $Id: msnd.h,v 1.33 1998/11/05 20:26:18 andrewtv Exp $
  *
  ********************************************************************/
 #ifndef __MSND_H
 #define __MSND_H
 
-#define VERSION			"0.8.2.1"
+#define VERSION			"0.8.2.2"
 
 #define DEFSAMPLERATE		DSP_DEFAULT_SPEED
 #define DEFSAMPLESIZE		AFMT_U8
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.1.131/linux/drivers/sound/msnd_pinnacle.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/msnd_pinnacle.c	Wed Dec 16 12:52:01 1998
@@ -29,7 +29,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  *
- * $Id: msnd_pinnacle.c,v 1.66 1998/10/09 19:54:39 andrewtv Exp $
+ * $Id: msnd_pinnacle.c,v 1.73 1998/12/04 14:41:02 andrewtv Exp $
  *
  ********************************************************************/
 
@@ -67,7 +67,7 @@
 #endif
 
 #ifndef CONFIG_MSND_WRITE_NDELAY
-#  define CONFIG_MSND_WRITE_NDELAY	0
+#  define CONFIG_MSND_WRITE_NDELAY	1
 #endif
 
 #define get_play_delay_jiffies(size)	((size) * HZ *			\
@@ -379,14 +379,14 @@
 
 	switch (d) {
 	case SOUND_MIXER_VOLUME:
-	case SOUND_MIXER_SYNTH:
 	case SOUND_MIXER_PCM:
 	case SOUND_MIXER_LINE:
+	case SOUND_MIXER_IMIX:
+	case SOUND_MIXER_LINE1:
 #ifndef MSND_CLASSIC
 	case SOUND_MIXER_MIC:
+	case SOUND_MIXER_SYNTH:
 #endif
-	case SOUND_MIXER_IMIX:
-	case SOUND_MIXER_LINE1:
 		return (dev.left_levels[d] >> 8) * 100 / 0xff | 
 			(((dev.right_levels[d] >> 8) * 100 / 0xff) << 8);
 	default:
@@ -394,16 +394,30 @@
 	}
 }
 
-#define update_vol(a,b,s)									\
-	writew(dev.left_levels[a] * readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff / s,		\
-	       dev.SMA + SMA_##b##Left);							\
-	writew(dev.right_levels[a] * readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff / s,	\
+#define update_volm(a,b)					\
+	writew((dev.left_levels[a] >> 1) *			\
+	       readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff,	\
+	       dev.SMA + SMA_##b##Left);			\
+	writew((dev.right_levels[a] >> 1)  *			\
+	       readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff,	\
 	       dev.SMA + SMA_##b##Right);
 
-#define update_pot(d,s,ar)						\
-	writeb(dev.left_levels[d] >> 8, dev.SMA + SMA_##s##Left);	\
-	writeb(dev.right_levels[d] >> 8, dev.SMA + SMA_##s##Right);	\
-	if (msnd_send_word(&dev, 0, 0, ar) == 0)			\
+#define update_potm(d,s,ar)					\
+	writeb((dev.left_levels[d] >> 8) *			\
+	       readw(dev.SMA + SMA_wCurrMastVolLeft) / 0xffff,	\
+	       dev.SMA + SMA_##s##Left);			\
+	writeb((dev.right_levels[d] >> 8) *			\
+	       readw(dev.SMA + SMA_wCurrMastVolRight) / 0xffff,	\
+	       dev.SMA + SMA_##s##Right);			\
+	if (msnd_send_word(&dev, 0, 0, ar) == 0)		\
+		chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
+
+#define update_pot(d,s,ar)				\
+	writeb(dev.left_levels[d] >> 8,			\
+	       dev.SMA + SMA_##s##Left);		\
+	writeb(dev.right_levels[d] >> 8,		\
+	       dev.SMA + SMA_##s##Right);		\
+	if (msnd_send_word(&dev, 0, 0, ar) == 0)	\
 		chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
 
 static int mixer_set(int d, int value)
@@ -412,6 +426,7 @@
 	int right = (value & 0x0000ff00) >> 8;
 	int bLeft, bRight;
 	int wLeft, wRight;
+	int updatemaster = 0;
 
 	if (d > 31)
 		return -EINVAL;
@@ -426,66 +441,66 @@
 	dev.right_levels[d] = wRight;
 
 	switch (d) {
-	case SOUND_MIXER_VOLUME:		/* master volume */
-		writew(wLeft / 2, dev.SMA + SMA_wCurrMastVolLeft);
-		writew(wRight / 2, dev.SMA + SMA_wCurrMastVolRight);
-		break;
-
-		/* pot controls */
-	case SOUND_MIXER_LINE:			/* aux pot control */
+		/* master volume unscaled controls */
+	case SOUND_MIXER_LINE:			/* line pot control */
+		/* scaled by IMIX in digital mix */
 		writeb(bLeft, dev.SMA + SMA_bInPotPosLeft);
 		writeb(bRight, dev.SMA + SMA_bInPotPosRight);
 		if (msnd_send_word(&dev, 0, 0, HDEXAR_IN_SET_POTS) == 0)
 			chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
 		break;
-
 #ifndef MSND_CLASSIC
 	case SOUND_MIXER_MIC:			/* mic pot control */
+		/* scaled by IMIX in digital mix */
 		writeb(bLeft, dev.SMA + SMA_bMicPotPosLeft);
 		writeb(bRight, dev.SMA + SMA_bMicPotPosRight);
 		if (msnd_send_word(&dev, 0, 0, HDEXAR_MIC_SET_POTS) == 0)
 			chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
 		break;
 #endif
-
-	case SOUND_MIXER_LINE1:			/* line pot control */
-		writeb(bLeft, dev.SMA + SMA_bAuxPotPosLeft);
-		writeb(bRight, dev.SMA + SMA_bAuxPotPosRight);
-		if (msnd_send_word(&dev, 0, 0, HDEXAR_AUX_SET_POTS) == 0)
-			chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
-		break;
+	case SOUND_MIXER_VOLUME:		/* master volume */
+		writew(wLeft, dev.SMA + SMA_wCurrMastVolLeft);
+		writew(wRight, dev.SMA + SMA_wCurrMastVolRight);
+		/* fall through */
+
+	case SOUND_MIXER_LINE1:			/* aux pot control */
+		/* scaled by master volume */
+		/* fall through */
 
 		/* digital controls */
 	case SOUND_MIXER_SYNTH:			/* synth vol (dsp mix) */
 	case SOUND_MIXER_PCM:			/* pcm vol (dsp mix) */
 	case SOUND_MIXER_IMIX:			/* input monitor (dsp mix) */
+		/* scaled by master volume */
+		updatemaster = 1;
 		break;
 
 	default:
 		return 0;
 	}
 
-	/* update digital controls for master volume */
-	update_vol(SOUND_MIXER_PCM, wCurrPlayVol, 1);
-	update_vol(SOUND_MIXER_IMIX, wCurrInVol, 1);
+	if (updatemaster) {
+		/* update master volume scaled controls */
+		update_volm(SOUND_MIXER_PCM, wCurrPlayVol);
+		update_volm(SOUND_MIXER_IMIX, wCurrInVol);
 #ifndef MSND_CLASSIC
-	update_vol(SOUND_MIXER_SYNTH, wCurrMHdrVol, 1);
+		update_volm(SOUND_MIXER_SYNTH, wCurrMHdrVol);
 #endif
-	
+		update_potm(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS);
+	}
+
 	return mixer_get(d);
 }
 
 static void mixer_setup(void)
 {
 	update_pot(SOUND_MIXER_LINE, bInPotPos, HDEXAR_IN_SET_POTS);
+	update_potm(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS);
+	update_volm(SOUND_MIXER_PCM, wCurrPlayVol);
+	update_volm(SOUND_MIXER_IMIX, wCurrInVol);
 #ifndef MSND_CLASSIC
 	update_pot(SOUND_MIXER_MIC, bMicPotPos, HDEXAR_MIC_SET_POTS);
-#endif
-	update_pot(SOUND_MIXER_LINE1, bAuxPotPos, HDEXAR_AUX_SET_POTS);
-	update_vol(SOUND_MIXER_PCM, wCurrPlayVol, 1);
-	update_vol(SOUND_MIXER_IMIX, wCurrInVol, 1);
-#ifndef MSND_CLASSIC
-	update_vol(SOUND_MIXER_SYNTH, wCurrMHdrVol, 1);
+	update_volm(SOUND_MIXER_SYNTH, wCurrMHdrVol);
 #endif
 }
 
@@ -501,7 +516,7 @@
 		dev.recsrc ^= recsrc;
 
 #ifndef MSND_CLASSIC
-	if (dev.recsrc & SOUND_MASK_LINE) {
+	if (dev.recsrc & SOUND_MASK_IMIX) {
 		if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0)
 			chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
 	}
@@ -518,7 +533,7 @@
 		/* Select no input (?) */
 		dev.recsrc = 0;
 #else
-		dev.recsrc = SOUND_MASK_LINE;
+		dev.recsrc = SOUND_MASK_IMIX;
 		if (msnd_send_word(&dev, 0, 0, HDEXAR_SET_ANA_IN) == 0)
 			chk_send_dsp_cmd(&dev, HDEX_AUX_REQ);
 #endif
@@ -545,13 +560,15 @@
 		set_mixer_info();
 		info.modify_counter = dev.mixer_mod_count;
 		return copy_to_user((void *)arg, &info, sizeof(info));
-	}
-	else if (cmd == SOUND_OLD_MIXER_INFO) {
+	} else if (cmd == SOUND_OLD_MIXER_INFO) {
 		_old_mixer_info info;
 		set_mixer_info();
 		return copy_to_user((void *)arg, &info, sizeof(info));
-	}
-	else if (((cmd >> 8) & 0xff) == 'M') {
+	} else if (cmd == SOUND_MIXER_PRIVATE1) {
+		dev.nresets = 0;
+		dsp_full_reset();
+		return 0;
+	} else if (((cmd >> 8) & 0xff) == 'M') {
 		int val = 0;
 		
 		if (_SIOC_DIR(cmd) & _SIOC_WRITE) {
@@ -570,8 +587,7 @@
 			}
 			++dev.mixer_mod_count;
 			return put_user(val, (int *)arg);
-		}
-		else {
+		} else {
 			switch (cmd & 0xff) {
 			case SOUND_MIXER_RECSRC:
 				val = dev.recsrc;
@@ -579,21 +595,22 @@
 				
 			case SOUND_MIXER_DEVMASK:
 			case SOUND_MIXER_STEREODEVS:
-				val =   SOUND_MASK_VOLUME |
+				val =   SOUND_MASK_PCM |
+					SOUND_MASK_LINE |
+					SOUND_MASK_IMIX |
+					SOUND_MASK_LINE1 |
 #ifndef MSND_CLASSIC
-					SOUND_MASK_SYNTH |
 					SOUND_MASK_MIC |
+					SOUND_MASK_SYNTH |
 #endif
-					SOUND_MASK_PCM |
-					SOUND_MASK_LINE |
-					SOUND_MASK_IMIX;
+					SOUND_MASK_VOLUME;
 				break;
 				  
 			case SOUND_MIXER_RECMASK:
 #ifdef MSND_CLASSIC
 				val =   0;
 #else
-				val =   SOUND_MASK_LINE |
+				val =   SOUND_MASK_IMIX |
 					SOUND_MASK_SYNTH;
 				if (test_bit(F_HAVEDIGITAL, &dev.flags))
 					val |= SOUND_MASK_DIGITAL1;
@@ -639,7 +656,9 @@
 	if (!(dev.mode & FMODE_WRITE) || !test_bit(F_WRITING, &dev.flags))
 		return;
 	set_bit(F_WRITEFLUSH, &dev.flags);
-	interruptible_sleep_on_timeout(&dev.writeflush, get_play_delay_jiffies(dev.DAPF.len) + HZ / 8);
+	interruptible_sleep_on_timeout(
+		&dev.writeflush,
+		get_play_delay_jiffies(dev.DAPF.len));
 	clear_bit(F_WRITEFLUSH, &dev.flags);
 	if (!signal_pending(current)) {
 		current->state = TASK_INTERRUPTIBLE;
@@ -727,6 +746,16 @@
 	set_default_rec_audio_parameters();
 }
 
+static void mod_inc_ref(void)
+{
+	MOD_INC_USE_COUNT;
+}
+
+static void mod_dec_ref(void)
+{
+	MOD_DEC_USE_COUNT;
+}
+
 static int dev_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
@@ -760,7 +789,7 @@
 		err = -EINVAL;
 	
 	if (err >= 0)
-		MOD_INC_USE_COUNT;
+		mod_inc_ref();
 
 	return err;
 }
@@ -791,7 +820,7 @@
 
 	if (err >= 0)
 #endif
-		MOD_DEC_USE_COUNT;
+		mod_dec_ref();
 
 #ifndef LINUX20	
 	return err;
@@ -919,7 +948,9 @@
 
 		if (count > 0) {
 			set_bit(F_READBLOCK, &dev.flags);
-			if (!interruptible_sleep_on_timeout(&dev.readblock, get_rec_delay_jiffies(DAR_BUFF_SIZE)))
+			if (!interruptible_sleep_on_timeout(
+				&dev.readblock,
+				get_rec_delay_jiffies(DAR_BUFF_SIZE)))
 				clear_bit(F_READING, &dev.flags);
 			clear_bit(F_READBLOCK, &dev.flags);
 			if (signal_pending(current))
@@ -960,7 +991,9 @@
 
 		if (count > 0) {
 			set_bit(F_WRITEBLOCK, &dev.flags);
-			interruptible_sleep_on_timeout(&dev.writeblock, get_play_delay_jiffies(DAP_BUFF_SIZE));
+			interruptible_sleep_on_timeout(
+				&dev.writeblock,
+				get_play_delay_jiffies(DAP_BUFF_SIZE));
 			clear_bit(F_WRITEBLOCK, &dev.flags);
 			if (signal_pending(current))
 				return -EINTR;
@@ -1054,7 +1087,8 @@
 			break;
 
 		default:
-/*			printk(KERN_DEBUG LOGNAME ": DSP message %d 0x%02x\n", LOBYTE(wMessage), LOBYTE(wMessage)); */
+/*			printk(KERN_DEBUG LOGNAME ": DSP message %d 0x%02x\n",
+			LOBYTE(wMessage), LOBYTE(wMessage)); */
 			break;
 		}
 		break;
@@ -1150,11 +1184,9 @@
 		return -ENODEV;
 	}
 
-	printk(KERN_INFO LOGNAME ": DSP reset successful\n");
-
 #ifdef MSND_CLASSIC
 	dev.name = "Classic/Tahiti/Monterey";
-	printk(KERN_INFO LOGNAME ": Turtle Beach %s, "
+	printk(KERN_INFO LOGNAME ": %s, "
 #else
 	switch (dev.info >> 4) {
 	case 0xf: xv = "<= 1.15"; break;
@@ -1177,7 +1209,7 @@
 		dev.name = pinfiji;
 		break;
 	}
-	printk(KERN_INFO LOGNAME ": Turtle Beach %s revision %s, Xilinx version %s, "
+	printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, "
 #endif /* MSND_CLASSIC */
 	       "I/O 0x%x-0x%x, IRQ %d, memory mapped to 0x%p-0x%p\n",
 	       dev.name,
@@ -1275,26 +1307,20 @@
 
 __initfunc(static int calibrate_adc(WORD srate))
 {
-	if (!dev.calibrate_signal) {
-		printk(KERN_INFO LOGNAME ": ADC calibration to board ground ");
+	writew(srate, dev.SMA + SMA_wCalFreqAtoD);
+	if (dev.calibrate_signal == 0)
 		writew(readw(dev.SMA + SMA_wCurrHostStatusFlags)
 		       | 0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
-	} else {
-		printk(KERN_INFO LOGNAME ": ADC calibration to signal ground ");
+	else
 		writew(readw(dev.SMA + SMA_wCurrHostStatusFlags)
 		       & ~0x0001, dev.SMA + SMA_wCurrHostStatusFlags);
-	}
-	
-	writew(srate, dev.SMA + SMA_wCalFreqAtoD);
-
 	if (msnd_send_word(&dev, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
 	    chk_send_dsp_cmd(&dev, HDEX_AUX_REQ) == 0) {
 		current->state = TASK_INTERRUPTIBLE;
 		schedule_timeout(HZ / 3);
-		printk("successful\n");
 		return 0;
 	}
-	printk("failed\n");
+	printk(KERN_WARNING LOGNAME ": ADC calibration failed\n");
 
 	return -EIO;
 }
@@ -1302,11 +1328,7 @@
 static int upload_dsp_code(void)
 {
 	outb(HPBLKSEL_0, dev.io + HP_BLKS);
-
-#ifdef HAVE_DSPCODEH
-	printk(KERN_INFO LOGNAME ": Using resident Turtle Beach DSP code\n");
-#else	
-	printk(KERN_INFO LOGNAME ": Loading Turtle Beach DSP code\n");
+#ifndef HAVE_DSPCODEH
 	INITCODESIZE = mod_firmware_load(INITCODEFILE, &INITCODE);
 	if (!INITCODE) {
 		printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);
@@ -1325,6 +1347,11 @@
 		printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");
 		return -ENODEV;
 	}
+#ifdef HAVE_DSPCODEH
+	printk(KERN_INFO LOGNAME ": DSP firmware uploaded (resident)\n");
+#else
+	printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n");
+#endif
 
 #ifndef HAVE_DSPCODEH
 	vfree(INITCODE);
@@ -1365,9 +1392,7 @@
 	if ((err = upload_dsp_code()) < 0) {
 		printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
 		return err;
-
-	} else
-		printk(KERN_INFO LOGNAME ": DSP upload successful\n");
+	}
 
 	timeout = 200;
 	while (readw(dev.base)) {
@@ -1390,8 +1415,8 @@
 	if (test_bit(F_RESETTING, &dev.flags) || ++dev.nresets > 10)
 		return 0;
 
-	printk(KERN_INFO LOGNAME ": Resetting DSP\n");
 	set_bit(F_RESETTING, &dev.flags);
+	printk(KERN_INFO LOGNAME ": DSP reset\n");
 	dsp_halt(NULL);			/* Unconditionally halt */
 	if ((rv = initialize()))
 		printk(KERN_WARNING LOGNAME ": DSP reset failed\n");
@@ -1441,13 +1466,11 @@
 		free_irq(dev.irq, &dev);
 		return dev.mixer_minor;
 	}
-	printk(KERN_INFO LOGNAME ": Using DSP minor %d, mixer minor %d\n", dev.dsp_minor, dev.mixer_minor);
 
 	disable_irq(dev.irq);
 	calibrate_adc(dev.play_sample_rate);
 #ifndef MSND_CLASSIC
-	printk(KERN_INFO LOGNAME ": Setting initial recording source to Line In\n");
-	force_recsrc(SOUND_MASK_LINE);
+	force_recsrc(SOUND_MASK_IMIX);
 #endif
 	
 	return 0;
@@ -1464,16 +1487,6 @@
 }
 #endif
 
-static void mod_inc_ref(void)
-{
-	MOD_INC_USE_COUNT;
-}
-
-static void mod_dec_ref(void)
-{
-	MOD_DEC_USE_COUNT;
-}
-
 #ifndef MSND_CLASSIC
 
 /* Pinnacle/Fiji Logical Device Configuration */
@@ -1896,14 +1909,10 @@
 		clear_bit(F_DISABLE_WRITE_NDELAY, &dev.flags);
 	else
 		set_bit(F_DISABLE_WRITE_NDELAY, &dev.flags);
-
 #ifndef MSND_CLASSIC
-	if (digital) {
+	if (digital)
 		set_bit(F_HAVEDIGITAL, &dev.flags);
-		printk(KERN_INFO LOGNAME ": Digital I/O access enabled\n");
-	}
 #endif
-
 	init_waitqueue(&dev.writeblock);
 	init_waitqueue(&dev.readblock);
 	init_waitqueue(&dev.writeflush);
@@ -1912,9 +1921,7 @@
 #ifndef LINUX20
 	spin_lock_init(&dev.lock);
 #endif
-
-	printk(KERN_INFO LOGNAME ": Using %u byte digital audio FIFOs (x2)\n", dev.fifosize);
-
+	printk(KERN_INFO LOGNAME ": %u byte audio FIFOs (x2)\n", dev.fifosize);
 	if ((err = msnd_fifo_alloc(&dev.DAPF, dev.fifosize)) < 0) {
 		printk(KERN_ERR LOGNAME ": Couldn't allocate write FIFO\n");
 		return err;
@@ -1946,10 +1953,7 @@
 #ifdef MODULE
 void cleanup_module(void)
 {
-	printk(KERN_INFO LOGNAME ": Unloading\n");
-
 	unload_multisound();
-
 	msnd_fifo_free(&dev.DAPF);
 	msnd_fifo_free(&dev.DARF);
 }
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/opl3sa2.c linux/drivers/sound/opl3sa2.c
--- v2.1.131/linux/drivers/sound/opl3sa2.c	Fri Oct 23 22:01:22 1998
+++ linux/drivers/sound/opl3sa2.c	Thu Dec 17 09:04:49 1998
@@ -1,19 +1,32 @@
 /*
  * sound/opl3sa2.c
  *
- * A low level driver for Yamaha OPL3-SA[2,3,x] based cards.
+ * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
+ * SAx cards should work, as they are just variants of the SA3.
  *
- * Scott Murray, Jun 14, 1998
+ * Copyright 1998 Scott Murray <scottm@interlog.com>
  *
- */
-
-/* Based on the CS4232 driver:
+ * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
+ * and others.  Now incorporates code/ideas from pss.c, also by Hannu
+ * Savolainen.  Both of those files are distributed with the following
+ * license:
+ *
+ * "Copyright (C) by Hannu Savolainen 1993-1997
+ *
+ *  OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
+ *  Version 2 (June 1991). See the "COPYING" file distributed with this software
+ *  for more info."
+ *
+ * As such, in accordance with the above license, this file, opl3sa2.c, is
+ * distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).
+ * See the "COPYING" file distributed with this software for more information.
  *
- * Copyright (C) by Hannu Savolainen 1993-1997
+ * Change History
+ * --------------
+ * Scott Murray            Original driver (Jun 14, 1998)
+ * Paul J.Y. Lahaie        Changed probing / attach code order
+ * Scott Murray            Added mixer support (Dec 03, 1998)
  *
- * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
- * Version 2 (June 1991). See the "COPYING" file distributed with this software
- * for more info.
  */
 
 #include <linux/config.h>
@@ -22,8 +35,369 @@
 #include "sound_config.h"
 #include "soundmodule.h"
 
+/* Useful control port indexes: */
+#define OPL3SA2_MASTER_LEFT  0x07
+#define OPL3SA2_MASTER_RIGHT 0x08
+#define OPL3SA2_MIC          0x09
+#define OPL3SA2_MISC         0x0A
+
+#define OPL3SA3_WIDE         0x14
+#define OPL3SA3_BASS         0x15
+#define OPL3SA3_TREBLE       0x16
+
+/* Useful constants: */
+#define DEFAULT_VOLUME 50
+#define DEFAULT_MIC    50
+#define DEFAULT_TIMBRE 0
+
+#define CHIPSET_UNKNOWN -1
+#define CHIPSET_OPL3SA2  1
+#define CHIPSET_OPL3SA3  2
+#define CHIPSET_OPL3SAX  4
+
+
 #ifdef CONFIG_OPL3SA2
 
+/* What's my version? */
+static int chipset_version = CHIPSET_UNKNOWN;
+
+/* Oh well, let's just cache the name */
+static char chipset_name[16];
+
+/* Where's my mixer */
+static int opl3sa2_mixer = -1;
+
+/* Bag o' mixer data */
+typedef struct opl3sa2_mixerdata {
+	unsigned short cfg_port;
+	unsigned short padding;
+	int            ad_mixer_dev;
+	unsigned int   volume_l;
+	unsigned int   volume_r;
+	unsigned int   mic;
+	unsigned int   bass;
+	unsigned int   treble;
+} opl3sa2_mixerdata;
+
+#ifdef CONFIG_OPL3SA2_CTRL_BASE
+/* Set control port if compiled into the kernel */
+static opl3sa2_mixerdata opl3sa2_data = { CONFIG_OPL3SA2_CTRL_BASE, };
+#else
+static opl3sa2_mixerdata opl3sa2_data;
+#endif
+
+static opl3sa2_mixerdata *devc = &opl3sa2_data;
+
+
+/* Standard read and write functions */
+
+static void opl3sa2_write(unsigned short port,
+			  unsigned char  index,
+			  unsigned char  data)
+{
+	outb_p(index, port);
+	outb(data, port + 1);
+}
+
+
+static void opl3sa2_read(unsigned short port,
+			 unsigned char  index,
+			 unsigned char* data)
+{
+	outb_p(index, port);
+	*data = inb(port + 1);
+}
+
+
+/* All of the mixer functions... */
+
+static void opl3sa2_set_volume(opl3sa2_mixerdata *devc, int left, int right)
+{
+	static unsigned char scale[101] = {
+		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 
+		0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 
+		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 
+		0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 
+		0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 
+		0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
+		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 
+		0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 
+		0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+		0x00
+	};
+	unsigned char vol;
+
+	vol = scale[left];
+
+	/* If level is zero, turn on mute */
+	if(!left)
+		vol |= 0x80;
+
+	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_LEFT, vol);
+
+	vol = scale[right];
+
+	/* If level is zero, turn on mute */
+	if(!right)
+		vol |= 0x80;
+
+	opl3sa2_write(devc->cfg_port, OPL3SA2_MASTER_RIGHT, vol);
+}
+
+
+static void opl3sa2_set_mic(opl3sa2_mixerdata *devc, int level)
+{
+	unsigned char vol = 0x1F;
+
+	if((level >= 0) && (level <= 100))
+		vol = 0x1F - (unsigned char) (0x1F * level / 100L);
+
+	/* If level is zero, turn on mute */
+	if(!level)
+		vol |= 0x80;
+
+	opl3sa2_write(devc->cfg_port, OPL3SA2_MIC, vol);
+}
+
+
+static void opl3sa3_set_bass(opl3sa2_mixerdata *devc, int level)
+{
+	unsigned char bass;
+
+	bass = level ? ((unsigned char) (0x07 * level / 100L)) : 0; 
+	bass |= (bass << 4);
+
+	opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
+}
+
+
+static void opl3sa3_set_treble(opl3sa2_mixerdata *devc, int level)
+{	
+	unsigned char treble;
+
+	treble = level ? ((unsigned char) (0x07 * level / 100L)) : 0; 
+	treble |= (treble << 4);
+
+	opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
+}
+
+
+static void opl3sa2_mixer_reset(opl3sa2_mixerdata *devc)
+{
+	if(devc)
+	{
+		opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
+		devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
+
+		opl3sa2_set_mic(devc, DEFAULT_MIC);
+		devc->mic = DEFAULT_MIC;
+
+		opl3sa3_set_bass(devc, DEFAULT_TIMBRE);
+		opl3sa3_set_treble(devc, DEFAULT_TIMBRE);
+		devc->bass = devc->treble = DEFAULT_TIMBRE;
+	}
+}
+
+
+static void arg_to_volume_mono(unsigned int volume, int *aleft)
+{
+	int left;
+	
+	left = volume & 0x00ff;
+	if (left > 100)
+		left = 100;
+	*aleft = left;
+}
+
+
+static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright)
+{
+	arg_to_volume_mono(volume, aleft);
+	arg_to_volume_mono(volume >> 8, aright);
+}
+
+
+static int ret_vol_mono(int left)
+{
+	return ((left << 8) | left);
+}
+
+
+static int ret_vol_stereo(int left, int right)
+{
+	return ((right << 8) | left);
+}
+
+
+static int call_ad_mixer(opl3sa2_mixerdata *devc, unsigned int cmd, caddr_t arg)
+{
+	if(devc->ad_mixer_dev != -1) 
+		return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev,
+							     cmd,
+							     arg);
+	else 
+		return -EINVAL;
+}
+
+
+static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	int cmdf = cmd & 0xff;
+
+	opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
+	
+	switch(cmdf)
+	{
+		case SOUND_MIXER_VOLUME:
+		case SOUND_MIXER_MIC:
+		case SOUND_MIXER_BASS:
+		case SOUND_MIXER_TREBLE:
+		case SOUND_MIXER_DEVMASK:
+		case SOUND_MIXER_STEREODEVS: 
+		case SOUND_MIXER_RECMASK:
+		case SOUND_MIXER_CAPS: 
+		case SOUND_MIXER_RECSRC:
+			break;
+
+		default:
+			return call_ad_mixer(devc, cmd, arg);
+	}
+	
+	if(((cmd >> 8) & 0xff) != 'M')
+		return -EINVAL;
+		
+	if(_SIOC_DIR (cmd) & _SIOC_WRITE)
+	{
+		switch (cmdf)	
+		{
+			case SOUND_MIXER_RECSRC:
+				if(devc->ad_mixer_dev != -1)
+					return call_ad_mixer(devc, cmd, arg);
+				else
+				{
+					if(*(int *)arg != 0)
+						return -EINVAL;
+					return 0;
+				}
+
+			case SOUND_MIXER_VOLUME:
+				arg_to_volume_stereo(*(unsigned int *)arg,
+						     &devc->volume_l,
+						     &devc->volume_r); 
+				opl3sa2_set_volume(devc, devc->volume_l,
+						   devc->volume_r);
+				return ret_vol_stereo(devc->volume_l,
+						      devc->volume_r);
+		  
+			case SOUND_MIXER_MIC:
+				arg_to_volume_mono(*(unsigned int *)arg,
+						   &devc->mic);
+				opl3sa2_set_mic(devc, devc->mic);
+				return ret_vol_mono(devc->mic);
+		  
+			case SOUND_MIXER_BASS:
+				if(chipset_version != CHIPSET_OPL3SA2)
+				{
+					arg_to_volume_mono(*(unsigned int *)arg,
+							   &devc->bass);
+					opl3sa3_set_bass(devc, devc->bass);
+					return ret_vol_mono(devc->bass);
+				}
+				return -EINVAL;
+		  
+			case SOUND_MIXER_TREBLE:
+				if(chipset_version != CHIPSET_OPL3SA2)
+				{
+					arg_to_volume_mono(*(unsigned int *)arg,
+							   &devc->treble);
+					opl3sa3_set_treble(devc, devc->treble);
+					return ret_vol_mono(devc->treble);
+				}
+				return -EINVAL;
+		  
+			default:
+				return -EINVAL;
+		}
+	}
+	else			
+	{
+		/*
+		 * Return parameters
+		 */
+		switch (cmdf)
+		{
+			case SOUND_MIXER_DEVMASK:
+				if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
+					*(int*)arg = 0; /* no mixer devices */
+
+				if(chipset_version != CHIPSET_OPL3SA2)
+					return (*(int*)arg |= SOUND_MASK_VOLUME |
+						              SOUND_MASK_MIC |
+						              SOUND_MASK_BASS |
+						              SOUND_MASK_TREBLE);
+				/* OPL3-SA2 has no bass and treble mixers */
+				return (*(int*)arg |= SOUND_MASK_VOLUME |
+					              SOUND_MASK_MIC);
+		  
+			case SOUND_MIXER_STEREODEVS:
+				if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
+					*(int*)arg = 0; /* no stereo devices */
+				return (*(int*)arg |= SOUND_MASK_VOLUME);
+		  
+			case SOUND_MIXER_RECMASK:
+				if(devc->ad_mixer_dev != -1)
+					return call_ad_mixer(devc, cmd, arg);
+				else
+					return (*(int*)arg = 0); /* no record devices */
+
+			case SOUND_MIXER_CAPS:
+				if(devc->ad_mixer_dev != -1)
+					return call_ad_mixer(devc, cmd, arg);
+				else
+					return (*(int*)arg = SOUND_CAP_EXCL_INPUT);
+
+			case SOUND_MIXER_RECSRC:
+				if(devc->ad_mixer_dev != -1)
+					return call_ad_mixer(devc, cmd, arg);
+				else
+					return (*(int*)arg = 0); /* no record source */
+
+			case SOUND_MIXER_VOLUME:
+				return (*(int*)arg = ret_vol_stereo(devc->volume_l,
+								    devc->volume_r));
+			  
+			case SOUND_MIXER_MIC:
+				return (*(int*)arg = ret_vol_mono(devc->mic));
+
+			case SOUND_MIXER_BASS:
+				if(chipset_version != CHIPSET_OPL3SA2)
+					return (*(int*)arg = ret_vol_mono(devc->bass));
+				return -EINVAL;
+
+			  
+			case SOUND_MIXER_TREBLE:
+				if(chipset_version != CHIPSET_OPL3SA2)
+					return (*(int*)arg = ret_vol_mono(devc->treble));
+				return -EINVAL;
+			  
+			default:
+				return -EINVAL;
+		}
+	}
+}
+
+
+static struct mixer_operations opl3sa2_mixer_operations =
+{
+	"Yamaha",
+	"",
+	 opl3sa2_mixer_ioctl
+};
+
+/* End of mixer-related stuff */
+
+
 int probe_opl3sa2_mpu(struct address_info *hw_config)
 {
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
@@ -50,82 +424,126 @@
 }
 
 
-int probe_opl3sa2_mss(struct address_info *hw_config)
+static int probe_opl3sa2_mss(struct address_info *hw_config)
 {
 	return probe_ms_sound(hw_config);
 }
 
 
-void attach_opl3sa2_mss(struct address_info *hw_config)
+static void attach_opl3sa2_mss(struct address_info *hw_config)
 {
-   	printk(KERN_INFO "opl3sa2.c: trying to init WSS\n");   
-   
-	attach_ms_sound(hw_config);
+	char mixer_name[64];
 
-   	/* request_region(hw_config->io_base, 4, "Yamaha 7xx WSS Config"); */
-   
-	if (hw_config->slots[0] != -1 &&
-	    audio_devs[hw_config->slots[0]]->mixer_dev != -1)
+	/* Create pretty names for mixer stuff */
+	strncpy(mixer_name, chipset_name, 16);
+	strncat(mixer_name, " and AD1848 (through MSS)", 64);
+
+	strncpy(opl3sa2_mixer_operations.name, chipset_name, 16);
+	strncat(opl3sa2_mixer_operations.name, "-AD1848", 64);
+
+	/* Install master mixer */
+	devc->ad_mixer_dev = -1;
+	if((opl3sa2_mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
+						mixer_name,
+						&opl3sa2_mixer_operations,
+						sizeof(struct mixer_operations),
+						devc)) < 0) 
 	{
-  		AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
-  		AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
-	        /* GSM! test the following: */
-                AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+		printk(KERN_ERR "Could not install %s master mixer\n", chipset_name);
+		return;
 	}
-}
 
+	opl3sa2_mixer_reset(devc);
 
-void unload_opl3sa2_mss(struct address_info *hw_config)
-{
-        int mixer;
-
-        /* Find mixer */
-	mixer = audio_devs[hw_config->slots[0]]->mixer_dev;
-
-        /* Unload MSS audio codec */
-	unload_ms_sound(hw_config);
-
-	sound_unload_audiodev(hw_config->slots[0]);
-
-        /* Unload mixer if there */
-	if(mixer >= 0)
+	attach_ms_sound(hw_config);	/* Slot 0 */
+	if(hw_config->slots[0] != -1)
 	{
-		sound_unload_mixerdev(mixer);
+		/* Did the MSS driver install? */
+		if(num_mixers == (opl3sa2_mixer + 2))
+		{
+			/* The MSS mixer is installed */
+			devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
+
+			/* Reroute mixers appropiately */
+			AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
+			AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
+			AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
+		}
 	}
+}
+
 
-        /* Release MSS config ports */
-	release_region(hw_config->io_base, 4);
+static void unload_opl3sa2_mss(struct address_info *hw_config)
+{
+	unload_ms_sound(hw_config);
 }
 
 
 int probe_opl3sa2(struct address_info *hw_config)
 {
+	char tag;
+
 	/*
 	 * Verify that the I/O port range is free.
 	 */
-
-	printk(KERN_INFO "opl3sa2.c: Control using I/O port 0x%03x\n", hw_config->io_base);
-
-	if (check_region(hw_config->io_base, 2))
+	if(check_region(hw_config->io_base, 2))
 	{
-	    printk(KERN_ERR "opl3sa2.c: Control I/O port 0x%03x not free\n", hw_config->io_base);
+	    printk(KERN_ERR
+		   "opl3sa2.c: Control I/O port 0x%03x not free\n",
+		   hw_config->io_base);
 	    return 0;
 	}
 
-	/* GSM!: Add some kind of other test here... */
+	/*
+	 * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
+	 */
+	chipset_version = 0;
+	opl3sa2_read(hw_config->io_base,
+		     OPL3SA2_MISC,
+		     (unsigned char*) &chipset_version);
+	chipset_version &= 0x0007;
+	switch(chipset_version)
+	{
+		case CHIPSET_OPL3SA2:
+			printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
+			tag = '2';
+			break;
+
+		case CHIPSET_OPL3SA3:
+			printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
+			tag = '3';
+			break;
+
+		case CHIPSET_OPL3SAX:
+			printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
+			tag = 'x';
+			break;
+
+		default:
+			printk(KERN_ERR "No Yamaha audio controller found\n");
+			printk(KERN_INFO
+			       "opl3sa2.c: chipset version = %x\n",
+			       chipset_version);
+			chipset_version = CHIPSET_UNKNOWN;
+			tag = '?';
+			break;
+	}
 
-	return 1;
+	if(chipset_version != CHIPSET_UNKNOWN) {
+		/* Generate a pretty name */
+		sprintf(chipset_name, "OPL3-SA%c", tag);
+		return 1;
+	}
+	return 0;
 }
 
 
 void attach_opl3sa2(struct address_info *hw_config)
 {
-   	printk(KERN_INFO "opl3sa2.c: trying to init!\n");   
-   
-   	request_region(hw_config->io_base, 2, "Yamaha 7xx Control");
+   	request_region(hw_config->io_base, 2, chipset_name);
 
-	/* GSM! Mixer stuff should go here... */
-}   
+	devc->cfg_port = hw_config->io_base;
+}
 
 
 void unload_opl3sa2(struct address_info *hw_config)
@@ -133,7 +551,9 @@
         /* Release control ports */
 	release_region(hw_config->io_base, 2);
 
-	/* GSM! Mixer stuff should go here... */
+	/* Unload mixer */
+	if(opl3sa2_mixer >= 0)
+		sound_unload_mixerdev(opl3sa2_mixer);
 }
 
 
@@ -146,12 +566,26 @@
 int dma     = -1;
 int dma2    = -1;
 
-MODULE_PARM(io,"i");
-MODULE_PARM(mss_io,"i");
-MODULE_PARM(mpu_io,"i");
-MODULE_PARM(irq,"i");
-MODULE_PARM(dma,"i");
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
+
+MODULE_PARM(mss_io, "i");
+MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
+
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be on 4 location boundaries and must be from 0x300 to 0x334)");
+
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
+
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
+
 MODULE_PARM(dma2,"i");
+MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
+
+MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
+MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
 
 EXPORT_NO_SYMBOLS;
 
@@ -159,17 +593,19 @@
 struct address_info mss_cfg;
 struct address_info mpu_cfg;
 
+
 /*
- *	Install a OPL3SA2 based card. Need to have ad1848 and mpu401
- *	loaded ready.
+ * Install a OPL3SA2 based card.
+ *
+ * Need to have ad1848 and mpu401 loaded ready.
  */
 int init_module(void)
 {
         int i;
 
-	if (io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
+	if(io == -1 || irq == -1 || dma == -1 || dma2 == -1 || mss_io == -1)
 	{
-		printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n");
+		printk(KERN_ERR "opl3sa2.c: io, mss_io, irq, dma, and dma2 must be set.\n");
 		return -EINVAL;
 	}
    
@@ -189,19 +625,20 @@
 	/* Call me paranoid: */
 	for(i = 0; i < 6; i++)
 	{
-	    cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1;
+		cfg.slots[i] = mss_cfg.slots[i] = mpu_cfg.slots[i] = -1;
 	}
 
-	if (probe_opl3sa2(&cfg) == 0)
+	if(probe_opl3sa2(&cfg) == 0)
 	{
-	    return -ENODEV;
+		return -ENODEV;
 	}
-	attach_opl3sa2(&cfg);
 
-	if (probe_opl3sa2_mss(&mss_cfg) == 0)
+	if(probe_opl3sa2_mss(&mss_cfg) == 0)
 	{
-	    return -ENODEV;
+		return -ENODEV;
 	}
+
+	attach_opl3sa2(&cfg);
 	attach_opl3sa2_mss(&mss_cfg);
 
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
@@ -213,9 +650,9 @@
 	    mpu_cfg.dma           = dma;
 	    mpu_cfg.always_detect = 1;  /* It's there, so use shared IRQs */
 
-	    if (probe_opl3sa2_mpu(&mpu_cfg))
+	    if(probe_opl3sa2_mpu(&mpu_cfg))
 	    {
-	        attach_opl3sa2_mpu(&mpu_cfg);
+		    attach_opl3sa2_mpu(&mpu_cfg);
 	    }
 	}
 #endif
@@ -229,7 +666,7 @@
 #if (defined(CONFIG_MPU401) || defined(CONFIG_MPU_EMU)) && defined(CONFIG_MIDI)
         if(mpu_cfg.slots[1] != -1)
 	{
-            unload_opl3sa2_mpu(&mpu_cfg);
+		unload_opl3sa2_mpu(&mpu_cfg);
 	}
 #endif
 	unload_opl3sa2_mss(&mss_cfg);
@@ -237,5 +674,5 @@
 	SOUND_LOCK_END;
 }
 
-#endif
-#endif
+#endif /* MODULE */
+#endif /* CONFIG_OPL3SA2 */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v2.1.131/linux/drivers/sound/pss.c	Thu Sep 17 17:53:37 1998
+++ linux/drivers/sound/pss.c	Wed Dec 16 12:52:01 1998
@@ -135,7 +135,7 @@
 	 * loops.
 	 */
 
-	for (i = 0; i < 5000000 && jiffies < limit; i++)
+	for (i = 0; i < 5000000 && time_before(jiffies, limit); i++)
  	{
  		if (inw(REG(PSS_STATUS)) & PSS_WRITE_EMPTY)
  		{
@@ -285,7 +285,7 @@
 		outw(0x00fe, REG(PSS_DATA));
 
 		limit = jiffies + HZ/10;
-		for (i = 0; i < 32768 && jiffies < limit; i++)
+		for (i = 0; i < 32768 && time_before(jiffies, limit); i++)
 			if (inw(REG(PSS_DATA)) == 0x5500)
 				break;
 
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- v2.1.131/linux/drivers/sound/sb_audio.c	Thu Nov 12 16:21:22 1998
+++ linux/drivers/sound/sb_audio.c	Wed Dec 16 12:52:01 1998
@@ -91,6 +91,14 @@
 {
 	sb_devc *devc = audio_devs[dev]->devc;
 
+	/* if we did dma juggling put the right dmap in the right place */
+	if(devc->duplex && audio_devs[dev]->dmap_out->dma != devc->dma8)
+	{
+		struct dma_buffparms *dmap_temp;
+		dmap_temp = audio_devs[dev]->dmap_out;
+		audio_devs[dev]->dmap_out = audio_devs[dev]->dmap_in;
+		audio_devs[dev]->dmap_in = dmap_temp;
+	}
 	audio_devs[dev]->dmap_out->dma = devc->dma8;
 	audio_devs[dev]->dmap_in->dma = ( devc->duplex ) ?
 		devc->dma16 : devc->dma8;
@@ -1136,6 +1144,12 @@
 	}
 }
 
+static void
+sb16_audio_mmap(int dev)
+{
+	sb_devc       *devc = audio_devs[dev]->devc;
+	devc->fullduplex = 0;
+}
 
 static struct audio_driver sb1_audio_driver =	/* SB1.x */
 {
@@ -1254,7 +1268,10 @@
 	sb16_audio_trigger,
 	sb16_audio_set_speed,
 	sb16_audio_set_bits,
-	sbpro_audio_set_channels
+	sbpro_audio_set_channels,
+	NULL,
+	NULL,
+	sb16_audio_mmap
 };
 
 static struct audio_driver ess_audio_driver =	/* ESS ES688/1688 */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.1.131/linux/drivers/sound/sb_common.c	Wed Dec 16 10:32:55 1998
+++ linux/drivers/sound/sb_common.c	Wed Dec 16 12:52:01 1998
@@ -975,9 +975,11 @@
 			if (devc->dma16 >= 0)
 				sound_free_dma(devc->dma16);
 		}
-		if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI) && devc->irq > 0)
+		if (!(devc->caps & SB_NO_AUDIO && devc->caps & SB_NO_MIDI))
 		{
-			free_irq(devc->irq, devc);
+			if (devc->irq > 0);
+				free_irq(devc->irq, devc);
+
 			sound_unload_mixerdev(devc->my_mixerdev);
 			/* We don't have to do this bit any more the UART401 is its own
 				master  -- Krzysztof Halasa */
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/sequencer.c linux/drivers/sound/sequencer.c
--- v2.1.131/linux/drivers/sound/sequencer.c	Sun Nov  8 14:03:03 1998
+++ linux/drivers/sound/sequencer.c	Wed Dec 16 12:52:01 1998
@@ -82,7 +82,7 @@
 static volatile int seq_playing = 0;
 static volatile int sequencer_busy = 0;
 static int      output_threshold;
-static int      pre_event_timeout;
+static long     pre_event_timeout;
 static unsigned synth_open_mask;
 
 static int      seq_queue(unsigned char *note, char nonblock);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.1.131/linux/drivers/sound/sonicvibes.c	Sun Nov  8 14:03:04 1998
+++ linux/drivers/sound/sonicvibes.c	Thu Dec 17 09:04:49 1998
@@ -47,6 +47,7 @@
  *                     Now mixer behaviour can basically be selected between
  *                     "OSS documented" and "OSS actual" behaviour
  *    31.08.98   0.7   Fix realplayer problems - dac.count issues
+ *    10.12.98   0.8   Fix drain_dac trying to wait on not yet initialized DMA
  *
  */
 
@@ -1226,7 +1227,7 @@
 	unsigned long flags;
 	int count, tmo;
 
-	if (s->dma_dac.mapped)
+	if (s->dma_dac.mapped || !s->dma_dac.ready)
 		return 0;
         current->state = TASK_INTERRUPTIBLE;
         add_wait_queue(&s->dma_dac.wait, &wait);
@@ -2277,7 +2278,7 @@
 
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-	printk(KERN_INFO "sv: version v0.7 time " __TIME__ " " __DATE__ "\n");
+	printk(KERN_INFO "sv: version v0.8 time " __TIME__ " " __DATE__ "\n");
 #if 0
 	if (!(wavetable_mem = __get_free_pages(GFP_KERNEL, 20-PAGE_SHIFT)))
 		printk(KERN_INFO "sv: cannot allocate 1MB of contiguous nonpageable memory for wavetable data\n");
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/sound_calls.h linux/drivers/sound/sound_calls.h
--- v2.1.131/linux/drivers/sound/sound_calls.h	Fri Oct 23 22:01:22 1998
+++ linux/drivers/sound/sound_calls.h	Wed Dec 16 12:52:01 1998
@@ -205,6 +205,11 @@
 int probe_ss_ms_sound (struct address_info *hw_config);
 void attach_ss_ms_sound(struct address_info * hw_config);
 
+/* From ad1816.c */
+void unload_ad1816(struct address_info *hw_info);
+int probe_ad1816 (struct address_info *hw_config);
+void attach_ad1816 (struct address_info *hw_config);
+
 /* From aedsp16.c */
 int InitAEDSP16_SBPRO(struct address_info *hw_config);
 int InitAEDSP16_MSS(struct address_info *hw_config);
@@ -281,29 +286,10 @@
 int probe_vidc(struct address_info *hw_config);
 void unload_vidc(struct address_info *hw_config);
 
-/*      From wavefront.c */
-void attach_wavefront (struct address_info *hw_config);
-int probe_wavefront (struct address_info *hw_config);
-void unload_wavefront (struct address_info *hw_config);
-
-/*      From wf_midi.c */
-void attach_wf_mpu(struct address_info * hw_config);
-int probe_wf_mpu(struct address_info *hw_config);
-void unload_wf_mpu(struct address_info *hw_config);
-int virtual_midi_enable (int mididev, struct address_info *);
-void virtual_midi_disable (int mididev);
-
-/*      From wavefront.c */
-void attach_wavefront (struct address_info *hw_config);
-int probe_wavefront (struct address_info *hw_config);
-void unload_wavefront (struct address_info *hw_config);
-
-/*      From wf_midi.c */
-void attach_wf_mpu(struct address_info * hw_config);
-int probe_wf_mpu(struct address_info *hw_config);
-void unload_wf_mpu(struct address_info *hw_config);
-int virtual_midi_enable (int mididev, struct address_info *);
-void virtual_midi_disable (int mididev);
+/*	From waveartist.c */
+void attach_waveartist(struct address_info *hw_config);
+int probe_waveartist(struct address_info *hw_config);
+void unload_waveartist(struct address_info *hw_config);
 
 /*      From wavefront.c */
 void attach_wavefront (struct address_info *hw_config);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.1.131/linux/drivers/sound/soundcard.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/sound/soundcard.c	Wed Dec 16 12:52:01 1998
@@ -760,6 +760,9 @@
 
 	dmap->mapping_flags |= DMA_MAP_MAPPED;
 
+	if( audio_devs[dev]->d->mmap)
+		audio_devs[dev]->d->mmap(dev);
+
 	memset(dmap->raw_buf,
 	       dmap->neutral_byte,
 	       dmap->bytes_in_use);
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/vidc.c linux/drivers/sound/vidc.c
--- v2.1.131/linux/drivers/sound/vidc.c	Tue Apr 14 14:29:24 1998
+++ linux/drivers/sound/vidc.c	Wed Dec 16 12:52:01 1998
@@ -6,32 +6,50 @@
  *	Copyright (C) 1997 by Russell King <rmk@arm.uk.linux.org>
  */
 
+#include <linux/module.h>
+#include <linux/kernel.h>
+
 #include <asm/io.h>
 #include <asm/dma.h>
 #include "sound_config.h"
+#include "soundmodule.h"
 #include "vidc.h"
 
 int vidc_busy;
 
-void vidc_update_filler(int bits, int channels)
+void vidc_update_filler(int format, int channels)
 {
-	int filltype;
+	int fillertype;
+
+#define TYPE(fmt,ch) (((fmt)<<2) | ((ch)&3))
 
-	filltype = bits + channels;
-	switch (filltype)
+	fillertype = TYPE(format, channels);
+printk("filler type: %X\n", fillertype);
+	switch (fillertype)
 	{
 		default:
-		case 9:
-			vidc_filler = vidc_fill_1x8;
+		case TYPE(AFMT_U8, 1):
+			vidc_filler = vidc_fill_1x8_u;
 			break;
-		case 10:
-			vidc_filler = vidc_fill_2x8;
+
+		case TYPE(AFMT_U8, 2):
+			vidc_filler = vidc_fill_2x8_u;
 			break;
-		case 17:
-			vidc_filler = vidc_fill_1x16;
+
+		case TYPE(AFMT_S8, 1):
+			vidc_filler = vidc_fill_1x8_s;
 			break;
-		case 18:
-			vidc_filler = vidc_fill_2x16;
+
+		case TYPE(AFMT_S8, 2):
+			vidc_filler = vidc_fill_2x8_s;
+			break;
+
+		case TYPE(AFMT_S16_LE, 1):
+			vidc_filler = vidc_fill_1x16_s;
+			break;
+
+		case TYPE(AFMT_S16_LE, 2):
+			vidc_filler = vidc_fill_2x16_s;
 			break;
 	}
 }
@@ -55,12 +73,12 @@
 		printk(KERN_ERR "VIDCsound: can't allocate virtual DMA channel\n");
 		return;
 	}
-	if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, "VIDCsound", NULL))
+	if (request_irq(hw_config->irq, vidc_sound_dma_irq, 0, "VIDCsound", &dma_start))
 	{
 		printk(KERN_ERR "VIDCsound: can't allocate DMA interrupt\n");
 		return;
 	}
-	vidc_synth_init(hw_config);
+//	vidc_synth_init(hw_config);
 	vidc_audio_init(hw_config);
 	vidc_mixer_init(hw_config);
 }
@@ -76,6 +94,32 @@
 
 void unload_vidc(struct address_info *hw_config)
 {
+	int i;
+
 	free_irq(hw_config->irq, NULL);
 	sound_free_dma(hw_config->dma);
+
+	for (i = 0; i < 2; i++)
+		free_page(dma_buf[i]);
+}
+
+#ifdef MODULE
+static struct address_info config;
+
+int init_module(void)
+{
+	if (probe_vidc(&config) == 0)
+		return -ENODEV;
+	printk("VIDC 16-bit serial sound\n");
+	SOUND_LOCK;
+	attach_vidc(&config);
+	return 0;
 }
+
+void cleanup_module(void)
+{
+	unload_vidc(&config);
+	SOUND_LOCK_END;
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/vidc.h linux/drivers/sound/vidc.h
--- v2.1.131/linux/drivers/sound/vidc.h	Wed Apr  8 19:36:28 1998
+++ linux/drivers/sound/vidc.h	Wed Dec 16 12:52:01 1998
@@ -16,14 +16,18 @@
  * Filler routines for different channels and sample sizes
  */
 
-extern unsigned long vidc_fill_1x8(unsigned long ibuf, unsigned long iend,
-				   unsigned long obuf, int mask);
-extern unsigned long vidc_fill_2x8(unsigned long ibuf, unsigned long iend,
-				   unsigned long obuf, int mask);
-extern unsigned long vidc_fill_1x16(unsigned long ibuf, unsigned long iend,
-				    unsigned long obuf, int mask);
-extern unsigned long vidc_fill_2x16(unsigned long ibuf, unsigned long iend,
-				    unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x8_u(unsigned long ibuf, unsigned long iend,
+				     unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x8_u(unsigned long ibuf, unsigned long iend,
+				     unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x8_s(unsigned long ibuf, unsigned long iend,
+				     unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x8_s(unsigned long ibuf, unsigned long iend,
+				     unsigned long obuf, int mask);
+extern unsigned long vidc_fill_1x16_s(unsigned long ibuf, unsigned long iend,
+				      unsigned long obuf, int mask);
+extern unsigned long vidc_fill_2x16_s(unsigned long ibuf, unsigned long iend,
+				      unsigned long obuf, int mask);
 
 /*
  * DMA Interrupt handler
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/vidc_audio.c linux/drivers/sound/vidc_audio.c
--- v2.1.131/linux/drivers/sound/vidc_audio.c	Tue Apr 14 14:29:24 1998
+++ linux/drivers/sound/vidc_audio.c	Wed Dec 16 12:52:01 1998
@@ -8,6 +8,8 @@
 
 #include <asm/hardware.h>
 #include <asm/io.h>
+#include <asm/system.h>
+
 #include "sound_config.h"
 #include "vidc.h"
 
@@ -22,7 +24,7 @@
 
 static int      vidc_audio_volume;
 static int      vidc_audio_rate;
-static char     vidc_audio_bits;
+static char     vidc_audio_format;
 static char     vidc_audio_channels;
 
 extern void     vidc_update_filler(int bits, int channels);
@@ -38,23 +40,25 @@
 	return vidc_audio_volume;
 }
 
-static int vidc_audio_set_bits(int bits)
+static int vidc_audio_set_bits(int fmt)
 {
-	switch (bits)
+printk("setting format: %d\n", fmt);
+	switch (fmt)
 	{
 		case AFMT_QUERY:
 			break;
 		case AFMT_U8:
+		case AFMT_S8:
 		case AFMT_S16_LE:
-			vidc_audio_bits = bits;
-			vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+			vidc_audio_format = fmt;
+			vidc_update_filler(vidc_audio_format, vidc_audio_channels);
 			break;
 		default:
-			vidc_audio_bits = 16;
-			vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+			vidc_audio_format = AFMT_S16_LE;
+			vidc_update_filler(vidc_audio_format, vidc_audio_channels);
 			break;
 	}
-	return vidc_audio_bits;
+	return vidc_audio_format;
 }
 
 static int vidc_audio_set_rate(int rate)
@@ -68,8 +72,8 @@
 			vidc_audio_rate = 3;
 		if (vidc_audio_rate > 255)
 			vidc_audio_rate = 255;
-		outl((vidc_audio_rate - 2) | 0xb0000000, VIDC_BASE);
-		outl(0xb1000003, VIDC_BASE);
+		outl((vidc_audio_rate - 2) | 0xb0000000, IO_VIDC_BASE);
+		outl(0xb1000003, IO_VIDC_BASE);
 		newsize = (10000 / vidc_audio_rate) & ~3;
 		if (newsize < 208)
 			newsize = 208;
@@ -92,11 +96,11 @@
 		case 1:
 		case 2:
 			vidc_audio_channels = channels;
-			vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+			vidc_update_filler(vidc_audio_format, vidc_audio_channels);
 			break;
 		default:
 			vidc_audio_channels = 2;
-			vidc_update_filler(vidc_audio_bits, vidc_audio_channels);
+			vidc_update_filler(vidc_audio_format, vidc_audio_channels);
 			break;
 	}
 	return vidc_audio_channels;
@@ -110,7 +114,6 @@
  *
  * Called when opening the DMAbuf               (dmabuf.c:259)
  */
-
 static int vidc_audio_open(int dev, int mode)
 {
 	if (vidc_busy)
@@ -133,7 +136,6 @@
  * Called when closing the DMAbuf               (dmabuf.c:477)
  *      after halt_xfer
  */
-
 static void vidc_audio_close(int dev)
 {
 	vidc_busy = 0;
@@ -205,23 +207,23 @@
  *  2.                                                  (dmabuf.c:1504)
  *  3. A new buffer needs to be sent to the device      (dmabuf.c:1579)
  */
- 
-static void vidc_audio_dma_interrupt(void)
-{
-	DMAbuf_outputintr(vidc_adev, 1);
-}
-
 static void vidc_audio_output_block(int dev, unsigned long buf, int total_count,
 			int intrflag)
 {
-	dma_start = buf;
+	struct audio_operations *adev = audio_devs[dev];
+	struct dma_buffparms *dmap = adev->dmap_out;
+
+	dma_start = buf - (unsigned long)dmap->raw_buf_phys + (unsigned long)dmap->raw_buf;
 	dma_count = total_count;
 
-	if (!intrflag)
+	if (!(adev->flags & DMA_ACTIVE))
 	{
-		dma_interrupt = vidc_audio_dma_interrupt;
+		unsigned long flags;
+printk("kicking output: %lX+%lX [%lX]\n", dma_start, dma_count, *(unsigned long *)dma_start);
+		save_flags_cli(flags);
 		vidc_sound_dma_irq(0, NULL, NULL);
-		outb(DMA_CR_D | DMA_CR_E, IOMD_SD0CR);
+		outb(DMA_CR_E | 0x10, IOMD_SD0CR);
+		restore_flags(flags);
 	}
 }
 
@@ -235,6 +237,11 @@
 	return -EINVAL;
 }
 
+static void vidc_audio_dma_interrupt(void)
+{
+	DMAbuf_outputintr(vidc_adev, 1);
+}
+
 /*
  * Prepare for outputting samples to `dev'
  *
@@ -246,34 +253,27 @@
  *  2. We get a write buffer without dma_mode setup     (dmabuf.c:1152)
  *  3. We restart a transfer                            (dmabuf.c:1324)
  */
-
 static int vidc_audio_prepare_for_output(int dev, int bsize, int bcount)
 {
+	audio_devs[dev]->dmap_out->flags |= DMA_NODMA;
+	dma_interrupt = vidc_audio_dma_interrupt;
 	return 0;
 }
 
-static void vidc_audio_reset(int dev)
-{
-}
-
 /*
- * Halt a DMA transfer to `dev'
- *
- * Called when:
- *  1. We close the DMAbuf                                      (dmabuf.c:476)
- *  2. We run out of output buffers to output to the device.    (dmabuf.c:1456)
- *  3. We run out of output buffers and we're closing down.     (dmabuf.c:1546)
- *  4. We run out of input buffers in AUTOMODE.                 (dmabuf.c:1651)
+ * Stop our current operation.
  */
- 
-static void vidc_audio_halt_xfer(int dev)
+static void vidc_audio_reset(int dev)
 {
-	dma_count = 0;
+	/* stop interrupts.  Our real interrupt routine
+	 * will close DMA down for us
+	 */
+	dma_interrupt = NULL;
 }
 
 static int vidc_audio_local_qlen(int dev)
 {
-	return dma_count != 0;
+	return /*dma_count !=*/ 0;
 }
 
 static struct audio_driver vidc_audio_driver =
@@ -286,35 +286,28 @@
 	vidc_audio_prepare_for_input,	/* prepare_for_input    */
 	vidc_audio_prepare_for_output,	/* prepare_for_output   */
 	vidc_audio_reset,		/* reset                */
-	vidc_audio_halt_xfer,		/* halt_xfer            */
 	vidc_audio_local_qlen,		/*+local_qlen           */
 	NULL,				/*+copy_from_user       */
 	NULL,				/*+halt_input           */
-	NULL,				/*+halt_output          */
+	NULL,				/* halt_output          */
 	NULL,				/*+trigger              */
 	NULL,				/*+set_speed            */
 	NULL,				/*+set_bits             */
 	NULL,				/*+set_channels         */
 };
 
-static struct audio_operations vidc_audio_operations =
-{
-	"VIDCsound",
-	0,
-	AFMT_U8 | AFMT_S16_LE,
-	NULL,
-	&vidc_audio_driver
-};
-
 void vidc_audio_init(struct address_info *hw_config)
 {
 	vidc_audio_volume = 100 | (100 << 8);
-	if ((vidc_adev = sound_alloc_audiodev())!=-1)
+
+	if ((vidc_adev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
+				"VIDCsound", &vidc_audio_driver,
+				sizeof(struct audio_driver),
+				DMA_AUTOMODE, AFMT_U8 | AFMT_S8 | AFMT_S16_LE,
+				NULL, hw_config->dma, hw_config->dma2)) >= 0)
 	{
-		audio_devs[vidc_adev] = &vidc_audio_operations;
 		audio_devs[vidc_adev]->min_fragment = 10;	/* 1024 bytes => 64 buffers */
 		audio_devs[vidc_adev]->mixer_dev = num_mixers;
-		audio_devs[vidc_adev]->flags |= 0;
 	}
 	else printk(KERN_ERR "VIDCsound: Too many PCM devices available\n");
 }
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/vidc_fill.S linux/drivers/sound/vidc_fill.S
--- v2.1.131/linux/drivers/sound/vidc_fill.S	Wed Apr  8 19:36:28 1998
+++ linux/drivers/sound/vidc_fill.S	Wed Dec 16 12:52:01 1998
@@ -12,11 +12,12 @@
 
 		.text
 
-ENTRY(vidc_fill_1x8)
+ENTRY(vidc_fill_1x8_u)
 		mov	ip, #0xff00
 1:		cmp	r0, r1
 		bge	SYMBOL_NAME(vidc_clear)
 		ldrb	r4, [r0], #1
+		eor	r4, r4, #0x80
 		and	r4, ip, r4, lsl #8
 		orr	r4, r4, r4, lsl #16
 		str	r4, [r2], #4
@@ -24,7 +25,7 @@
 		blt	1b
 		mov	pc, lr
 
-ENTRY(vidc_fill_2x8)
+ENTRY(vidc_fill_2x8_u)
 		mov	ip, #0xff00
 1:		cmp	r0, r1
 		bge	SYMBOL_NAME(vidc_clear)
@@ -38,7 +39,33 @@
 		blt	1b
 		mov	pc, lr
 
-ENTRY(vidc_fill_1x16)
+ENTRY(vidc_fill_1x8_s)
+		mov	ip, #0xff00
+1:		cmp	r0, r1
+		bge	SYMBOL_NAME(vidc_clear)
+		ldrb	r4, [r0], #1
+		and	r4, ip, r4, lsl #8
+		orr	r4, r4, r4, lsl #16
+		str	r4, [r2], #4
+		cmp	r2, r3
+		blt	1b
+		mov	pc, lr
+
+ENTRY(vidc_fill_2x8_s)
+		mov	ip, #0xff00
+1:		cmp	r0, r1
+		bge	SYMBOL_NAME(vidc_clear)
+		ldr	r4, [r0], #2
+		and	r5, r4, ip
+		and	r4, ip, r4, lsl #8
+		orr	r4, r4, r5, lsl #16
+		orr	r4, r4, r4, lsr #8
+		str	r4, [r2], #4
+		cmp	r2, r3
+		blt	1b
+		mov	pc, lr
+
+ENTRY(vidc_fill_1x16_s)
 		mov	ip, #0xff00
 		orr	ip, ip, ip, lsr #8
 1:		cmp	r0, r1
@@ -56,7 +83,7 @@
 		blt	1b
 		mov	pc, lr
 
-ENTRY(vidc_fill_2x16)
+ENTRY(vidc_fill_2x16_s)
 		mov	ip, #0xff00
 		orr	ip, ip, ip, lsr #8
 1:		cmp	r0, r1
@@ -103,26 +130,26 @@
  */
 
 ENTRY(vidc_sound_dma_irq)
-		stmfd	sp!, {r4 - r9, lr}
-		ldr	r9, =SYMBOL_NAME(dma_start)
-		ldmia	r9, {r0, r1, r2, r3, r4, r5}
+		stmfd	sp!, {r4 - r8, lr}
+		ldr	r8, =SYMBOL_NAME(dma_start)
+		ldmia	r8, {r0, r1, r2, r3, r4, r5}
 		teq	r1, #0
 		adreq	r4, SYMBOL_NAME(vidc_fill_noaudio)
-		moveq	r8, #1 << 31
-		movne	r8, #0
+		moveq	r7, #1 << 31
+		movne	r7, #0
 		mov	ip, #IOMD_BASE & 0xff000000
 		orr	ip, ip, #IOMD_BASE & 0x00ff0000
-		ldrb	r7, [ip, #IOMD_SD0ST]
-		tst	r7, #DMA_ST_OFL			@ Check for overrun
-		eorne	r7, r7, #DMA_ST_AB
-		tst	r7, #DMA_ST_AB
+		ldrb	r6, [ip, #IOMD_SD0ST]
+		tst	r6, #DMA_ST_OFL			@ Check for overrun
+		eorne	r6, r6, #DMA_ST_AB
+		tst	r6, #DMA_ST_AB
 		moveq	r2, r3				@ DMAing A, update B
 		add	r3, r2, r5			@ End of DMA buffer
 		add	r1, r1, r0			@ End of virtual DMA buffer
 		mov	lr, pc
-		mov	pc, r4				@ Call fill routine
+		mov	pc, r4				@ Call fill routine (uses r4, ip)
 		sub	r1, r1, r0			@ Remaining length
-		stmia	r9, {r0, r1}
+		stmia	r8, {r0, r1}
 		mov	r0, #0
 		tst	r2, #4				@ Round buffer up to 4 words
 		strne	r0, [r2], #4
@@ -133,29 +160,31 @@
 		mov	r2, r2, lsl #20
 		movs	r2, r2, lsr #20
 		orreq	r2, r2, #1 << 30		@ Set L bit
-		orr	r2, r2, r8
-		ldmdb	r9, {r3, r4, r5}
-		tst	r7, #DMA_ST_AB
+		orr	r2, r2, r7
+		ldmdb	r8, {r3, r4, r5}
+		tst	r6, #DMA_ST_AB
 		mov	ip, #IOMD_BASE & 0xff000000
 		orr	ip, ip, #IOMD_BASE & 0x00ff0000
 		streq	r4, [ip, #IOMD_SD0CURB]
 		strne	r5, [ip, #IOMD_SD0CURA]
 		streq	r2, [ip, #IOMD_SD0ENDB]
 		strne	r2, [ip, #IOMD_SD0ENDA]
-		ldr	r6, [ip, #IOMD_SD0ST]
-		tst	r6, #DMA_ST_OFL
+		ldr	lr, [ip, #IOMD_SD0ST]
+		tst	lr, #DMA_ST_OFL
 		bne	1f
-		tst	r7, #DMA_ST_AB
+		tst	r6, #DMA_ST_AB
 		strne	r4, [ip, #IOMD_SD0CURB]
 		streq	r5, [ip, #IOMD_SD0CURA]
 		strne	r2, [ip, #IOMD_SD0ENDB]
 		streq	r2, [ip, #IOMD_SD0ENDA]
-1:		teq	r8, #0
+1:		teq	r7, #0
 		mov	r0, #0x10
 		strneb	r0, [ip, #IOMD_SD0CR]
-		teqeq	r1, #0
-		ldmfd	sp!, {r4 - r9, lr}
-		moveq	pc, r3				@ Call interrupt routine
+		ldmfd	sp!, {r4 - r8, lr}
+		teq	r1, #0				@ If we have no more
+		movne	pc, lr
+		teq	r3, #0
+		movne	pc, r3				@ Call interrupt routine
 		mov	pc, lr
 
 		.data
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/vidc_mixer.c linux/drivers/sound/vidc_mixer.c
--- v2.1.131/linux/drivers/sound/vidc_mixer.c	Tue Apr 14 14:29:24 1998
+++ linux/drivers/sound/vidc_mixer.c	Wed Dec 16 12:52:01 1998
@@ -47,13 +47,15 @@
 			break;
 
 		case SOUND_MIXER_READ_SYNTH:
-			ret = vidc_synth_get_volume();
+//			ret = vidc_synth_get_volume();
+			ret = 0;
 			break;
 
 		case SOUND_MIXER_WRITE_SYNTH:
 			if (get_user(ret, (int *) arg))
 				return -EINVAL;
-			ret = vidc_synth_set_volume(ret);
+//			ret = vidc_synth_set_volume(ret);
+			ret = 0;
 			break;
 
 		case SOUND_MIXER_READ_PCM:
diff -u --recursive --new-file v2.1.131/linux/drivers/sound/vidc_synth.c linux/drivers/sound/vidc_synth.c
--- v2.1.131/linux/drivers/sound/vidc_synth.c	Tue Apr 14 14:29:24 1998
+++ linux/drivers/sound/vidc_synth.c	Wed Dec 16 12:52:01 1998
@@ -8,7 +8,7 @@
 
 #include "sound_config.h"
 #include "vidc.h"
-
+#if 0
 static struct synth_info vidc_info =
 {
 	"VIDCsound",		/* name                 */
@@ -42,31 +42,32 @@
 
 static struct synth_operations vidc_synth_operations =
 {
-	&vidc_info,		/* info                 */
-	0,			/* midi_dev             */
-	SYNTH_TYPE_SAMPLE,	/* synth_type           */
-				/*SAMPLE_TYPE_XXX */ 0,
-				/* SAMPLE_TYPE GUS *//* synth_subtype                */
-	vidc_synth_open,	/* open                 */
-	vidc_synth_close,	/* close                */
-	NULL,			/* ioctl                */
-	NULL,			/* kill_note            */
-	NULL,			/* start_note           */
-	NULL,			/* set_instr            */
-	NULL,			/* reset                */
-	NULL,			/* hw_control           */
-	NULL,			/* load_patch           */
-	NULL,			/* aftertouch           */
-	NULL,			/* controller           */
-	NULL,			/* panning              */
-	NULL,			/* volume_method        */
-	NULL,			/* patchmgr             */
-	NULL,			/* bender               */
-	NULL,			/* alloc                */
-	NULL,			/* setup_voice          */
-	NULL,			/* send_sysex           */
-				/* alloc                */
-				/* chn_info[16]         */
+	"VIDC Synth",		/* name			*/
+	&vidc_info,		/* info 		*/
+	0,			/* midi_dev		*/
+	SYNTH_TYPE_SAMPLE,	/* synth_type		*/
+	/*SAMPLE_TYPE_XXX */ 0, /* synth_subtype	*/
+	vidc_synth_open,	/* open 		*/
+	vidc_synth_close,	/* close		*/
+	NULL,			/* ioctl		*/
+	NULL,			/* kill_note		*/
+	NULL,			/* start_note		*/
+	NULL,			/* set_instr		*/
+	NULL,			/* reset		*/
+	NULL,			/* hw_control		*/
+	NULL,			/* load_patch		*/
+	NULL,			/* aftertouch		*/
+	NULL,			/* controller		*/
+	NULL,			/* panning		*/
+	NULL,			/* volume_method	*/
+	NULL,			/* bender		*/
+	NULL,			/* alloc_voice		*/
+	NULL,			/* setup_voice		*/
+	NULL,			/* send_sysex		*/
+				/* alloc		*/
+				/* chn_info[16] 	*/
+				/* syex_buf		*/
+				/* syex_ptr		*/
 };
 
 int  vidc_synth_get_volume(void)
@@ -87,3 +88,4 @@
 	else
 		printk(KERN_ERR "VIDCsound: Too many synthesizers\n");
 }
+#endif
diff -u --recursive --new-file v2.1.131/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.1.131/linux/drivers/video/Config.in	Fri Nov 27 13:09:25 1998
+++ linux/drivers/video/Config.in	Mon Dec 21 14:48:04 1998
@@ -156,7 +156,8 @@
 	 "$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_G364" = "y" -o \
 	 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
 	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
-         "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" ]; then
+         "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
+         "$CONFIG_FB_CT65550" = "y" ]; then
       define_bool CONFIG_FBCON_CFB8 y
     else
       if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -168,7 +169,8 @@
 	   "$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_G364" = "m" -o \
 	   "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
 	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
-           "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" ]; then
+           "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
+           "$CONFIG_FB_CT65550" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB8 m
       fi
     fi
@@ -178,7 +180,7 @@
 	 "$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 \
-	 "$CONFIG_FB_MATROX" = "y" ]; then
+	 "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" ]; then
       define_bool CONFIG_FBCON_CFB16 y
     else
       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -187,7 +189,7 @@
 	   "$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 \
-	   "$CONFIG_FB_MATROX" = "m" ]; then
+ 	   "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" ]; then
 	define_bool CONFIG_FBCON_CFB16 m
       fi
     fi
diff -u --recursive --new-file v2.1.131/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.1.131/linux/drivers/video/atyfb.c	Wed Dec 16 10:32:55 1998
+++ linux/drivers/video/atyfb.c	Mon Dec 21 14:48:04 1998
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.90 1998/11/20 12:27:03 geert Exp $
+/*  $Id: atyfb.c,v 1.93 1998/12/18 18:33:13 geert Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -1457,7 +1457,7 @@
     vco_div_count = pll->m & 0x3f;
     ref_div_count = pll->n;
 
-    *vclk_per = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
+    *vclk_per = ((ref_clk_per*ref_div_count)<<(3-df))/(vco_div_count+65);
 
     return 0;
 }
@@ -1719,6 +1719,22 @@
 	aty_set_pll_gx(info, &par->pll.gx);
 	aty_st_le32(BUS_CNTL, 0x890e20f1, info);
 	aty_st_le32(DAC_CNTL, 0x47052100, info);
+
+	/* Don't forget MEM_CNTL */
+	i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
+	switch (par->crtc.bpp) {
+	    case 8:
+		i |= 0x02000000;
+		break;
+	    case 16:
+		i |= 0x03000000;
+		break;
+	    case 32:
+		i |= 0x06000000;
+		break;
+	}
+	aty_st_le32(MEM_CNTL, i, info);
+					
     } else {
 	aty_set_pll_ct(info, &par->pll.ct);
 	i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff;
diff -u --recursive --new-file v2.1.131/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.1.131/linux/drivers/video/cgsixfb.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/cgsixfb.c	Mon Dec 21 14:48:04 1998
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.11 1998/09/04 15:43:42 jj Exp $
+/* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -534,6 +534,7 @@
 	unsigned int rev, conf;
 	struct cg6_tec *tec = fb->s.cg6.tec;
 	struct cg6_fbc *fbc = fb->s.cg6.fbc;
+	u32 mode;
 	
 	/* Turn off stuff in the Transform Engine. */
 	tec->tec_matrix = 0;
@@ -552,15 +553,20 @@
 		*(fb->s.cg6.fhc) = conf;
 	}
 
-	/* Set things in the FBC. */
-	fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
+	/* Set things in the FBC. Bad things appear to happen if we do
+	 * back to back store/loads on the mode register, so copy it
+	 * out instead. */
+	mode = fbc->mode;
+	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 |
 		       CG6_FBC_BDISP_MASK);
-	fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
+	mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
 		      CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
 		      CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
 		      CG6_FBC_BDISP_0);
+	fbc->mode = mode;
+
 	fbc->clip = 0;
 	fbc->offx = 0;
 	fbc->offy = 0;
diff -u --recursive --new-file v2.1.131/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.1.131/linux/drivers/video/chipsfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/chipsfb.c	Mon Dec 21 14:48:04 1998
@@ -358,6 +358,7 @@
 		if (con == currcon) {
 			write_cr(0x13, 200);		// 16 bit display width (decimal)
 			write_xr(0x81, 0x14);		// 15 bit (TrueColor) color mode
+			write_xr(0x82, 0x00);		// disable palettes
 			write_xr(0x20, 0x10);		// 16 bit blitter mode
 		}
 
@@ -379,6 +380,7 @@
 		if (con == currcon) {
 			write_cr(0x13, 100);		// 8 bit display width (decimal)
 			write_xr(0x81, 0x12);		// 8 bit color mode
+			write_xr(0x82, 0x08);		// Graphics gamma enable
 			write_xr(0x20, 0x00);		// 8 bit blitter mode
 		}
 
diff -u --recursive --new-file v2.1.131/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.1.131/linux/drivers/video/controlfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/controlfb.c	Mon Dec 21 14:48:04 1998
@@ -57,12 +57,6 @@
 
 #include "controlfb.h"
 
-static int currcon = 0;
-static int switching = 0;
-static char fontname[40] __initdata = { 0 };
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
-
 struct fb_par_control {
 	int	vmode, cmode;
 	int	xres, yres;
@@ -70,11 +64,25 @@
 	int	xoffset, yoffset;
 };
 
+#define DIRTY(z) ((x)->z != (y)->z)
+static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y)
+{
+	return (!DIRTY(vmode) && !DIRTY(cmode) && !DIRTY(xres)
+		&& !DIRTY(yres) && !DIRTY(vxres) && !DIRTY(vyres)
+		&& !DIRTY(xoffset) && !DIRTY(yoffset));
+}
+static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y)
+{
+	return (!DIRTY(bits_per_pixel) && !DIRTY(xres)
+		&& !DIRTY(yres) && !DIRTY(xres_virtual)
+		&& !DIRTY(yres_virtual));
+}
+
 struct fb_info_control {
 	struct fb_info			info;
-	struct fb_fix_screeninfo	fix;
-	struct fb_var_screeninfo	var;
-	struct display			disp;
+/*	struct fb_fix_screeninfo	fix;
+	struct fb_var_screeninfo	var;*/
+	struct display			display;
 	struct fb_par_control		par;
 	struct {
 		__u8 red, green, blue;
@@ -101,15 +109,7 @@
 	} fbcon_cmap;
 };
 
-/*
- * Exported functions
- */
-void control_init(void);
-#ifdef CONFIG_FB_OF
-void control_of_init(struct device_node *dp);
-#endif
-void controlfb_setup(char *options, int *ints);
-
+/******************** Prototypes for exported functions ********************/
 static int control_open(struct fb_info *info, int user);
 static int control_release(struct fb_info *info, int user);
 static int control_get_fix(struct fb_fix_screeninfo *fix, int con,
@@ -127,11 +127,38 @@
 static int control_ioctl(struct inode *inode, struct file *file, u_int cmd,
 		       u_long arg, int con, struct fb_info *info);
 
+
+static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,
+			     u_int *blue, u_int *transp, struct fb_info *info);
+static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+			     u_int transp, struct fb_info *info);
+
+/******************** Prototypes for internal functions ********************/
+static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
+	struct fb_info_control *p);
+static void do_install_cmap(int con, struct fb_info *info);
+static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p);
+
+/************************* Internal variables *****************************/
+static int currcon = 0;
+static int par_set = 0;
+static char fontname[40] __initdata = { 0 };
+static int default_vmode = VMODE_NVRAM;
+static int default_cmode = CMODE_NVRAM;
+
+/*
+ * Exported functions
+ */
+void control_init(void);
+#ifdef CONFIG_FB_OF
+void control_of_init(struct device_node *dp);
+#endif
+void control_setup(char *options, int *ints);
+
 static int read_control_sense(struct fb_info_control *p);
 static inline int control_vram_reqd(int video_mode, int color_mode);
 static void set_control_clock(unsigned char *params);
-static void control_set_hardware(struct fb_info_control *p);
-static void control_par_to_all(struct fb_info_control *p, int init);
+static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par);
 static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var);
 static int control_var_to_par(struct fb_var_screeninfo *var,
 	struct fb_par_control *par, const struct fb_info *fb_info);
@@ -139,10 +166,8 @@
 static void control_init_info(struct fb_info *info, struct fb_info_control *p);
 static void control_par_to_display(struct fb_par_control *par,
   struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p);
-static void control_init_display(struct display *disp);
-static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
-	struct fb_info_control *p);
-static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p);
+
+static int controlfb_updatevar(int con, struct fb_info *info);
 
 static struct fb_ops controlfb_ops = {
 	control_open,
@@ -156,15 +181,15 @@
 	control_ioctl
 };
 
-static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,
-			     u_int *blue, u_int *transp, struct fb_info *info);
-static int controlfb_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);
 
 
+/********************  The functions for controlfb_ops ********************/
+
+#ifndef MODULE
 __openfirmware
+#endif
 
+/**********  Dummies for loading control as a module  **********/
 
 static int control_open(struct fb_info *info, int user)
 {
@@ -178,25 +203,62 @@
 	return 0;
 }
 
+#ifdef MODULE
+int init_module(void)
+{
+	struct device_node *dp;
+
+	printk("Loading...\n");
+	dp = find_devices("control");
+	if (dp != 0)
+		control_of_init(dp);
+	else
+		printk("Failed.\n");
+	printk("Done.\n");
+}
+
+void cleanup_module(void)
+{
+}
+#endif
+
+/*********** Providing our information to the user ************/
+
 static int control_get_fix(struct fb_fix_screeninfo *fix, int con,
 			 struct fb_info *info)
 {
-	struct fb_info_control *cp = (struct fb_info_control *) info;
+	struct fb_info_control *p = (struct fb_info_control *) info;
 
-	*fix = cp->fix;
+	if(!par_set)
+		printk(KERN_ERR "control_get_fix called with unset par!\n");
+	if(con == -1) {
+		control_par_to_fix(&p->par, fix, p);
+	} else {
+		struct fb_par_control par;
+		
+		control_var_to_par(&fb_display[con].var, &par, info);
+		control_par_to_fix(&par, fix, p);
+	}
 	return 0;
 }
 
 static int control_get_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
-	struct fb_info_control *cp = (struct fb_info_control *) info;
+	struct fb_info_control *p = (struct fb_info_control *) info;
 
-	*var = cp->var;
+	if(!par_set)
+		printk(KERN_ERR "control_get_var called with unset par!\n");
+	if(con == -1) {
+		control_par_to_var(&p->par, var);
+	} else {
+		*var = fb_display[con].var;
+	}
 	return 0;
 }
 
 /* Sets everything according to var */
+/* No longer safe for use in console switching */
 static int control_set_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
@@ -204,53 +266,57 @@
 	struct display *disp;
 	struct fb_par_control par;
 	int depthchange, err;
+	int activate = var->activate;
+
+	disp = (con >= 0) ? &fb_display[con] : info->disp;
 
-	disp = (con >= 0) ? &fb_display[con] : &p->disp;
 	if((err = control_var_to_par(var, &par, info))) {
-		printk (KERN_ERR "Error in control_set_var, calling control_var_to_par: %d.\n", err);
+		printk (KERN_ERR "control_set_var: error calling control_var_to_par: %d.\n", err);
 		return err;
 	}
 	
-	if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) {
-		/* printk("Not activating, in control_set_var.\n"); */
-		control_par_to_var(&par, var);
+	control_par_to_var(&par, var);
+	
+	if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
 		return 0;
-	}
+
 /* I know, we want to use fb_display[con], but grab certain info from p->var instead. */
-#define DIRTY(x) (p->var.x != var->x)
-	depthchange = DIRTY(bits_per_pixel);
-	if(!DIRTY(xres) && !DIRTY(yres) && !DIRTY(xres_virtual) &&
-	   !DIRTY(yres_virtual) && !DIRTY(bits_per_pixel)) {
-	   	control_par_to_var(&par, var);
-		p->var = disp->var = *var;
-		return 0;
-	}
-	/* printk("Original bpp is %d, new bpp %d.\n", p->var.bits_per_pixel, var->bits_per_pixel); */
-	/* OK, we're getting here at the right times... */
-	p->par = par;
-	control_par_to_var(&par, var);
-	p->var = *var;
-	control_par_to_fix(&par, &p->fix, p);
-	control_par_to_display(&par, disp, &p->fix, p);
-	p->disp = *disp;
+/* [above no longer true] */
+	depthchange = (disp->var.bits_per_pixel != var->bits_per_pixel);
+	if(!VAR_MATCH(&disp->var, var)) {
+		struct fb_fix_screeninfo	fix;
+		control_par_to_fix(&par, &fix, p);
+		control_par_to_display(&par, disp, &fix, p);
+		if(info->changevar)
+			(*info->changevar)(con);
+	} else
+		disp->var = *var;
+	/*p->disp = *disp;*/
+
 	
-	if(info->changevar && !switching)	/* Don't want to do this if just switching consoles. */
-		(*info->changevar)(con);
-	if(con == currcon)
-		control_set_hardware(p);
-	if(depthchange)
+	if(con == currcon || con == -1) {
+		control_set_hardware(p, &par);
+	}
+	if(depthchange) {
 		if((err = fb_alloc_cmap(&disp->cmap, 0, 0)))
 			return err;
-	if(depthchange || switching)
 		do_install_cmap(con, info);
+	}
 	return 0;
 }
 
 static int control_pan_display(struct fb_var_screeninfo *var, int con,
 			     struct fb_info *info)
 {
-	if (var->xoffset != 0 || var->yoffset != 0)
+	struct fb_info_control *p = (struct fb_info_control *)info;
+	struct fb_par_control *par = &p->par;
+	
+	if (var->xoffset != 0 || var->yoffset+var->yres > var->yres_virtual)
 		return -EINVAL;
+	fb_display[con].var.yoffset =  par->yoffset = var->yoffset;
+	if(con == currcon)
+		out_le32(&p->control_regs->start_addr.r,
+		    par->yoffset * (par->vxres << par->cmode));
 	return 0;
 }
 
@@ -260,7 +326,7 @@
 	if (con == currcon)		/* current console? */
 		return fb_get_cmap(cmap, kspc, controlfb_getcolreg, info);
 	if (fb_display[con].cmap.len)	/* non default colormap? */
-		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc? 0: 2);
+		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0: 2);
 	else {
 		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
 		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);
@@ -275,12 +341,11 @@
 	int err;
 
 	if (disp->cmap.len == 0) {
-		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
+		int size = disp->var.bits_per_pixel == 16 ? 32 : 256;
 		err = fb_alloc_cmap(&disp->cmap, size, 0);
 		if (err)
 			return err;
 	}
-
 	if (con == currcon)
 		return fb_set_cmap(cmap, kspc, controlfb_setcolreg, info);
 	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);
@@ -293,30 +358,42 @@
 	return -EINVAL;
 }
 
+/********************  End of controlfb_ops implementation  ********************/
+/* (new one that is) */
+
+
 static int controlfb_switch(int con, struct fb_info *info)
 {
+	struct fb_info_control	*p = (struct fb_info_control *)info;
+	struct fb_par_control	par;
+	int oldcon = currcon;
+
 	if (fb_display[currcon].cmap.len)
 		fb_get_cmap(&fb_display[currcon].cmap, 1, controlfb_getcolreg,
 			    info);
 	currcon = con;
-#if 0
-	control_var_to_par(&fb_display[currcon].var, &par, info);
-	control_set_par(&par, info); /*STOPPEDHERE - did i define that? */
+
+	control_var_to_par(&fb_display[con].var, &par, info);
+	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);
+		controlfb_updatevar(con, info);
+
 	do_install_cmap(con, info);
-#else
-	/* I see no reason not to do this.  Minus info->changevar(). */
-	/* DOH.  This makes control_set_var compare, you guessed it, */
-	/* fb_display[con].var (first param), and fb_display[con].var! */
-	/* Perhaps I just fixed that... */
-	switching = 1;
-	control_set_var(&fb_display[con].var, con, info);
-	switching = 0;
-#endif
-	return 0;
+	return 1;
 }
 
 static int controlfb_updatevar(int con, struct fb_info *info)
 {
+	struct fb_info_control	*p = (struct fb_info_control *)info;
+
+	if(con != currcon)
+		return 0;
+	/* imsttfb blanks the unused bottom of the screen here...hmm. */
+	out_le32(&p->control_regs->start_addr.r,
+	    fb_display[con].var.yoffset * fb_display[con].line_length);
+	
 	return 0;
 }
 
@@ -332,10 +409,12 @@
  *    blank_mode == 3: suspend hsync
  *    blank_mode == 4: powerdown
  */
-/* [danj] I think there's something fishy about those constants... */
+/* A blank_mode of 1+VESA_NO_BLANKING or 1+VESA_POWERDOWN act alike... */
 	struct fb_info_control *p = (struct fb_info_control *) info;
 	int	ctrl;
 
+	if(blank_mode == 1+VESA_NO_BLANKING)
+		blank_mode = 1+VESA_POWERDOWN;
 	ctrl = ld_le32(&p->control_regs->ctrl.r) | 0x33;
 	if (blank_mode)
 		--blank_mode;
@@ -385,25 +464,16 @@
 	out_8(&p->cmap_regs->lut, blue);
 
 	if (regno < 16)
-		switch (p->var.bits_per_pixel) {
+		switch (p->par.cmode) {
 #ifdef FBCON_HAS_CFB16
-			case 16:
-#if 0
-				p->fbcon_cmap.cfb16[regno] = (red << 10) | (green << 5) | blue;
-#else
+			case CMODE_16:
 				p->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
-#endif
 				break;
 #endif
 #ifdef FBCON_HAS_CFB32
-			case 32:
-#if 0
-				p->fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue;
-#else
+			case CMODE_32:
 				i = (regno << 8) | regno;
 				p->fbcon_cmap.cfb32[regno] = (i << 16) | i;
-				/* I think */
-#endif
 				break;
 #endif
 		}
@@ -427,18 +497,12 @@
 #ifdef CONFIG_FB_COMPAT_XPMAC
 extern struct vc_mode display_info;
 extern struct fb_info *console_fb_info;
-#if 0
-extern int (*console_setmode_ptr)(struct vc_mode *, int);
-extern int (*console_set_cmap_ptr)(struct fb_cmap *, int, int,
-				   struct fb_info *);
-int console_setmode(struct vc_mode *, int);
-#endif
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 
 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]->pitch[color_mode];
+		* control_reg_init[video_mode-1]->hres << color_mode;
 }
 
 static void set_control_clock(unsigned char *params)
@@ -457,7 +521,9 @@
 
 __initfunc(static void init_control(struct fb_info_control *p))
 {
-	struct fb_par_control *par = &p->par;
+	struct fb_par_control parstruct;
+	struct fb_par_control *par = &parstruct;
+	struct fb_var_screeninfo var;
 
 	p->sense = read_control_sense(p);
 	printk(KERN_INFO "Monitor sense value = 0x%x, ", p->sense);
@@ -482,30 +548,44 @@
 	printk("using video mode %d and color mode %d.\n", par->vmode, par->cmode);
 	
 	par->vxres = par->xres = control_reg_init[par->vmode - 1]->hres;
-	par->vyres = par->yres = control_reg_init[par->vmode - 1]->vres;
+	par->yres = control_reg_init[par->vmode - 1]->vres;
+	par->vyres = p->total_vram / (par->vxres << par->cmode);
 	par->xoffset = par->yoffset = 0;
 	
-	control_par_to_all(p, 1);
+	control_init_info(&p->info, p);
+	
+	par_set = 1;	/* Debug */
+	
+	control_par_to_var(par, &var);
+	control_set_var(&var, -1, &p->info);
 	
 	p->info.flags = FBINFO_FLAG_DEFAULT;
 	if (register_framebuffer(&p->info) < 0) {
 		kfree(p);
 		return;
 	}
-	control_set_hardware(p);
 	
 	printk(KERN_INFO "fb%d: control display adapter\n", GET_FB_IDX(p->info.node));	
 }
 
+#define STORE_D2(a,d) \
+	out_8(&p->cmap_regs->addr, (a)); \
+	out_8(&p->cmap_regs->d2,   (d))
+
 /* Now how about actually saying, Make it so! */
 /* Some things in here probably don't need to be done each time. */
-static void control_set_hardware(struct fb_info_control *p)
+static void control_set_hardware(struct fb_info_control *p, struct fb_par_control *par)
 {
 	struct control_regvals	*init;
-	struct preg		*rp;
+	volatile struct preg	*rp;
 	int			flags, ctrl, i;
 	int			vmode, cmode;
 	
+	if(PAR_EQUAL(&p->par, par))
+		return;
+	
+	p->par = *par;
+	
 	vmode = p->par.vmode;
 	cmode = p->par.cmode;
 	
@@ -527,19 +607,20 @@
 	
 	set_control_clock(init->clock_params);
 	
-	p->cmap_regs->addr = 0x20; p->cmap_regs->d2 = init->radacal_ctrl[cmode];
-	p->cmap_regs->addr = 0x21; p->cmap_regs->d2 = p->control_use_bank2 ? 0: 1;
-	p->cmap_regs->addr = 0x10; p->cmap_regs->d2 = 0;
-	p->cmap_regs->addr = 0x11; p->cmap_regs->d2 = 0;
+	STORE_D2(0x20, init->radacal_ctrl[cmode]);
+	STORE_D2(0x21, p->control_use_bank2 ? 0 : 1);
+	STORE_D2(0x10, 0);
+	STORE_D2(0x11, 0);
 
 	rp = &p->control_regs->vswin;
 	for (i = 0; i < 16; ++i, ++rp)
 		out_le32(&rp->r, init->regs[i]);
 	
-	out_le32(&p->control_regs->pitch.r, init->pitch[cmode]);
+	out_le32(&p->control_regs->pitch.r, init->hres << 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, 0);
+	out_le32(&p->control_regs->start_addr.r,
+	    par->yoffset * (par->vxres << par->cmode));
 	out_le32(&p->control_regs->reg18.r, 0x1e5);
 	out_le32(&p->control_regs->reg19.r, 0);
 
@@ -556,11 +637,11 @@
 #ifdef CONFIG_FB_COMPAT_XPMAC
 	/* And let the world know the truth. */
 	if (!console_fb_info || console_fb_info == &p->info) {
-		display_info.height = p->var.yres;
-		display_info.width = p->var.xres;
+		display_info.height = p->par.yres;
+		display_info.width = p->par.xres;
 		display_info.depth = (cmode == CMODE_32) ? 32 :
 			((cmode == CMODE_16) ? 16 : 8);
-		display_info.pitch = p->fix.line_length;
+		display_info.pitch = p->par.vxres << p->par.cmode;
 		display_info.mode = vmode;
 		strncpy(display_info.name, "control",
 			sizeof(display_info.name));
@@ -591,15 +672,6 @@
 	unsigned long		addr, size;
 	int			i, bank1, bank2;
 
-#if 0
-	if(dp->next != 0)
-		printk("Warning: only using first control display device.\n");
-		/* danj: I have a feeling this no longer applies - if we somehow *
-		 * had two of them, they'd be two framebuffers, right?
-		 * Yep. - paulus
-		 */
-#endif
-
 	if(dp->n_addrs != 2) {
 		printk(KERN_ERR "expecting 2 address for control (got %d)", dp->n_addrs);
 		return;
@@ -629,25 +701,23 @@
 
 	/* Work out which banks of VRAM we have installed. */
 	/* danj: I guess the card just ignores writes to nonexistant VRAM... */
-	p->frame_buffer[0] = 0x5a;
-	p->frame_buffer[1] = 0xc7;
-	bank1 = p->frame_buffer[0] == 0x5a && p->frame_buffer[1] == 0xc7;
-	p->frame_buffer[0x600000] = 0xa5;
-	p->frame_buffer[0x600001] = 0x38;
-	bank2 = p->frame_buffer[0x600000] == 0xa5 && p->frame_buffer[0x600001] == 0x38;
+	out_8(&p->frame_buffer[0], 0x5a);
+	out_8(&p->frame_buffer[1], 0xc7);
+	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0]) : "memory" );
+	bank1 = (in_8(&p->frame_buffer[0]) == 0x5a) && (in_8(&p->frame_buffer[1]) == 0xc7);
+
+	out_8(&p->frame_buffer[0x600000], 0xa5);
+	out_8(&p->frame_buffer[0x600001], 0x38);
+	asm volatile("eieio; dcbi 0,%0" : : "r" (&p->frame_buffer[0x600000]) : "memory" );
+	bank2 = (in_8(&p->frame_buffer[0x600000]) == 0xa5)
+		&& (in_8(&p->frame_buffer[0x600001]) == 0x38);
+	
 	p->total_vram = (bank1 + bank2) * 0x200000;
 	/* If we don't have bank 1 installed, we hope we have bank 2 :-) */
 	p->control_use_bank2 = !bank1;
 	if (p->control_use_bank2)
 		p->frame_buffer += 0x600000;
 
-#ifdef CONFIG_FB_COMPAT_XPMAC
-#if 0
-	console_set_cmap_ptr = control_set_cmap;
-	console_setmode_ptr = control_console_setmode;
-#endif
-#endif /* CONFIG_FB_COMPAT_XPMAC */
-
 	init_control(p);
 }
 
@@ -655,8 +725,6 @@
  * Get the monitor sense value.
  * Note that this can be called before calibrate_delay,
  * so we can't use udelay.
- *
- * Hmm - looking at platinum, should we be calling eieio() here?
  */
 static int read_control_sense(struct fb_info_control *p)
 {
@@ -685,6 +753,7 @@
 	return sense;
 }
 
+/***********************  Various translation functions  ***********************/
 #if 1
 /* This routine takes a user-supplied var, and picks the best vmode/cmode from it. */
 static int control_var_to_par(struct fb_var_screeninfo *var,
@@ -726,59 +795,58 @@
 		par->vmode = VMODE_1280_960_75;		/* 1280x960, 75Hz */
 	else if (xres <= 1280 && yres <= 1024)
 		par->vmode = VMODE_1280_1024_75;	/* 1280x1024, 75Hz */
-	else
+	else {
+		printk(KERN_ERR "Bad x/y res in var_to_par\n");
 		return -EINVAL;
+	}
 
 	xres = control_reg_init[par->vmode-1]->hres;
 	yres = control_reg_init[par->vmode-1]->vres;
 
-/*
+	par->xres = xres;
+	par->yres = yres;
+
 	if (var->xres_virtual <= xres)
 		par->vxres = xres;
-	else
+	else if(var->xres_virtual > xres) {
+		par->vxres = xres;
+	} else	/* NotReached at present */
 		par->vxres = (var->xres_virtual+7) & ~7;
+
 	if (var->yres_virtual <= yres)
 		par->vyres = yres;
 	else
 		par->vyres = var->yres_virtual;
 
-	par->xoffset = (var->xoffset+7) & ~7;
-	par->yoffset = var->yoffset;
-	if (par->xoffset+xres > par->vxres || par->yoffset+yres > par->vyres)
-		return -EINVAL;
-*/
-
-	/* I'm too chicken to think about virtual	*/
-	/* resolutions just yet. Bok bok.			*/
-	
-	/* And I'm too chicken to even figure out what they are.  Awk awk. [danj] */
-	if (var->xres_virtual > xres || var->yres_virtual > yres
-		|| var->xoffset != 0 || var->yoffset != 0) {
+	if (var->xoffset > 0 || var->yoffset+yres > par->vyres) {
+		printk(KERN_ERR "Bad offsets in var_to_par\n");
 		return -EINVAL;
 	}
 
-	par->xres = xres;
-	par->yres = yres;
-	par->vxres = xres;
-	par->vyres = yres;
-	par->xoffset = 0;
-	par->yoffset = 0;
+	par->xoffset = (var->xoffset+7) & ~7;
+	par->yoffset = var->yoffset;
+
 
-	if (bpp <= 8)
+ 	if (bpp <= 8)
 		par->cmode = CMODE_8;
 	else if (bpp <= 16)
 		par->cmode = CMODE_16;
 	else if (bpp <= 32)
 		par->cmode = CMODE_32;
-	else
+	else {
+		printk(KERN_ERR "Bad bpp in var_to_par\n");
 		return -EINVAL;
+	}
 
-	if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram)
+	if (control_vram_reqd(par->vmode, par->cmode) > p->total_vram) {
+		printk(KERN_ERR "Too much VRAM required for vmode %d cmode %d.\n", par->vmode, par->cmode);
 		return -EINVAL;
+	}
 
 	/* Check if we know about the wanted video mode */
 	init = control_reg_init[par->vmode-1];
 	if (init == 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?		*/
 		return -EINVAL;
@@ -812,14 +880,19 @@
 }
 #endif
 
-#if 1
+/***********  Convert hardware data in par to an fb_var_screeninfo ***********/
+
 static void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
 {
+	struct control_regints *rv;
+	
+	rv = (struct control_regints *) control_reg_init[par->vmode - 1]->regs;
+	
 	memset(var, 0, sizeof(*var));
 	var->xres = control_reg_init[par->vmode - 1]->hres;
 	var->yres = control_reg_init[par->vmode - 1]->vres;
-	var->xres_virtual = var->xres;
-	var->yres_virtual = var->yres;	/* For now. */
+	var->xres_virtual = par->vxres;
+	var->yres_virtual = par->vyres;
 	var->xoffset = par->xoffset;
 	var->yoffset = par->yoffset;
 	var->grayscale = 0;
@@ -873,12 +946,30 @@
 	var->width = -1;
 	var->vmode = FB_VMODE_NONINTERLACED;
 
-	/* these are total guesses, copied right out of atyfb.c */
-	var->left_margin = var->right_margin = 64;
-	var->upper_margin = var->lower_margin = 32;
-	var->hsync_len = /*64*/8;
-	var->vsync_len = /*2*/8;
-	var->sync = 0;
+	var->left_margin = (rv->heblank - rv->hesync)
+		<< ((par->vmode > 18) ? 2 : 1);
+	var->right_margin = (rv->hssync - rv->hsblank)
+		<< ((par->vmode > 18) ? 2 : 1);
+	var->hsync_len = (rv->hperiod + 2 - rv->hssync + rv->hesync)
+		<< ((par->vmode > 18) ? 2 : 1);
+
+	var->upper_margin = (rv->veblank - rv->vesync) >> 1;
+	var->lower_margin = (rv->vssync - rv->vsblank) >> 1;
+	var->vsync_len = (rv->vperiod - rv->vssync + rv->vesync) >> 1;
+
+	/* Acording to macmodes.c... */
+	if((par->vmode >= 9 && par->vmode <= 12) ||
+	   (par->vmode >= 16 && par->vmode <= 18) ||
+	   (par->vmode == 20))
+	{
+		var->sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT;
+	} else {
+		var->sync = 0;          /* I suppose */
+	}
+
+    /* The reason these are both here: with my revised margin calculations, */
+    /* these SHOULD both give the same answer for each mode.  Some day I    */
+    /* will sit down and check the rest.  Works perfectly for vmode 13.     */
 
 #if 0
 /* jonh's pixclocks...*/
@@ -899,14 +990,9 @@
 	var->pixclock >>= control_reg_init[par->vmode-1]->clock_params[2];
 #endif
 }
-#else
-static inline void control_par_to_var(struct fb_par_control *par, struct fb_var_screeninfo *var)
-{
-	mac_vmode_to_var(par->vmode, par->cmode, var);
-}
-#endif
 
-static void control_init_fix(struct fb_fix_screeninfo *fix, struct fb_info_control *p)
+static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
+	struct fb_info_control *p)
 {
 	memset(fix, 0, sizeof(*fix));
 	strcpy(fix->id, "control");
@@ -914,34 +1000,35 @@
 	fix->mmio_len = sizeof(struct control_regs);
 	fix->type = FB_TYPE_PACKED_PIXELS;
 	
+	fix->ypanstep = 1;
 	/*
 		fix->type_aux = 0;
 		fix->ywrapstep = 0;
 		fix->ypanstep = 0;
 		fix->xpanstep = 0;
 	*/
-}
 
-/* Fix must already be inited ^^^^^^^ */
-static void control_par_to_fix(struct fb_par_control *par, struct fb_fix_screeninfo *fix,
-	struct fb_info_control *p)
-{
 	fix->smem_start = (void *)(p->frame_buffer_phys
 		+ control_reg_init[par->vmode-1]->offset[par->cmode]);
-	p->fix.smem_len = control_vram_reqd(par->vmode, par->cmode);
-		/* Hmm, jonh used total_vram here. */
-	p->fix.visual = (par->cmode == CMODE_8) ?
+	fix->smem_len = p->total_vram;
+	fix->visual = (par->cmode == CMODE_8) ?
 		FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
-	p->fix.line_length = par->vxres << par->cmode;
-		/* ywrapstep, xpanstep, ypanstep */
+	fix->line_length = par->vxres << par->cmode;
 }
 
-static void control_init_display(struct display *disp)
+/* We never initialize any display except for p->disp.
+   And p->disp is already memset to 0.  So no memset here.
+   [Found by Takashi Oe]
+*/
+static void control_par_to_display(struct fb_par_control *par,
+  struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p)
 {
-	memset(disp, 0, sizeof(*disp));
-	disp->type = /* fix->type */ FB_TYPE_PACKED_PIXELS;
+	/* memset(disp, 0, sizeof(*disp)); */
+	disp->type = fix->type;
 	disp->can_soft_blank = 1;
-	disp->scrollmode = SCROLL_YREDRAW;
+	disp->scrollmode = SCROLL_YNOMOVE | SCROLL_YNOPARTIAL;
+	disp->ypanstep = fix->ypanstep;
+	disp->ywrapstep = fix->ywrapstep;
 #if 0
 		disp->type_aux = fix->type_aux;
 		disp->cmap.red = NULL;	/* ??? danj */
@@ -950,22 +1037,18 @@
 		disp->cmap.transp = NULL;
 			/* Yeah, I realize I just set 0 = 0. */
 #endif
-}
 
-static void control_par_to_display(struct fb_par_control *par,
-  struct display *disp, struct fb_fix_screeninfo *fix, struct fb_info_control *p)
-{
-	disp->var = p->var;
+	control_par_to_var(par, &disp->var);
 	disp->screen_base = (char *) p->frame_buffer
 		 + control_reg_init[par->vmode-1]->offset[par->cmode];
 	disp->visual = fix->visual;
 	disp->line_length = fix->line_length;
-
-if(disp->scrollmode != SCROLL_YREDRAW) {
-	printk(KERN_ERR "Scroll mode not YREDRAW in control_par_to_display!!\n");
-	disp->scrollmode = SCROLL_YREDRAW;
+	control_set_dispsw(disp, par->cmode, p);
 }
-	switch (par->cmode) {
+
+static void control_set_dispsw(struct display *disp, int cmode, struct fb_info_control *p)
+{
+	switch (cmode) {
 #ifdef FBCON_HAS_CFB8
 		case CMODE_8:
 			disp->dispsw = &fbcon_cfb8;
@@ -991,10 +1074,10 @@
 
 static void control_init_info(struct fb_info *info, struct fb_info_control *p)
 {
-	strcpy(info->modename, p->fix.id);
+	strcpy(info->modename, "control");
 	info->node = -1;	/* ??? danj */
 	info->fbops = &controlfb_ops;
-	info->disp = &p->disp;
+	info->disp = &p->display;
 	strcpy(info->fontname, fontname);
 	info->changevar = NULL;
 	info->switch_con = &controlfb_switch;
@@ -1002,28 +1085,8 @@
 	info->blank = &controlfb_blank;
 }
 
-/* danj: Oh, I HOPE I didn't miss anything major in here... */
-static void control_par_to_all(struct fb_info_control *p, int init)
-{
-	if(init) {
-		control_init_fix(&p->fix, p);
-	}
-	control_par_to_fix(&p->par, &p->fix, p);
-
-	control_par_to_var(&p->par, &p->var);
-
-	if(init) {
-		control_init_display(&p->disp);
-	}
-	control_par_to_display(&p->par, &p->disp, &p->fix, p);
-	
-	if(init) {
-		control_init_info(&p->info, p);
-	}
-}
-
 /* Parse user speficied options (`video=controlfb:') */
-__initfunc(void controlfb_setup(char *options, int *ints))
+__initfunc(void control_setup(char *options, int *ints))
 {
 	char *this_opt;
 
@@ -1050,6 +1113,11 @@
 		} else if (!strncmp(this_opt, "cmode:", 6)) {
 			int depth = simple_strtoul(this_opt+6, NULL, 0);
 			switch (depth) {
+			 case CMODE_8:
+			 case CMODE_16:
+			 case CMODE_32:
+			 	default_cmode = depth;
+			 	break;
 			 case 8:
 				default_cmode = CMODE_8;
 				break;
@@ -1081,4 +1149,5 @@
 
     return 0;
 }
+
 #endif
diff -u --recursive --new-file v2.1.131/linux/drivers/video/controlfb.h linux/drivers/video/controlfb.h
--- v2.1.131/linux/drivers/video/controlfb.h	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/controlfb.h	Mon Dec 21 14:48:04 1998
@@ -73,6 +73,28 @@
 	struct preg res[6];
 };
 
+struct control_regints {
+	/* Vertical parameters are in units of 1/2 scan line */
+	unsigned vswin;	/* between vsblank and vssync */
+	unsigned vsblank;	/* vert start blank */
+	unsigned veblank;	/* vert end blank (display start) */
+	unsigned vewin;	/* between vesync and veblank */
+	unsigned vesync;	/* vert end sync */
+	unsigned vssync;	/* vert start sync */
+	unsigned vperiod;	/* vert period */
+	unsigned reg8;
+	/* Horizontal params are in units of 2 pixels */
+	/* Except, apparently, for hres > 1024 (or == 1280?) */
+	unsigned hperiod;	/* horiz period - 2 */
+	unsigned hsblank;	/* horiz start blank */
+	unsigned heblank;	/* horiz end blank */
+	unsigned hesync;	/* horiz end sync */
+	unsigned hssync;	/* horiz start sync */
+	unsigned rege;
+	unsigned regf;
+	unsigned reg10;
+};
+	
 /*
  * Register initialization tables for the control display.
  *
@@ -81,9 +103,10 @@
  *
  * The values for vertical frequency (V) in the comments below
  * are the values measured using the modes under MacOS.
+ *
+ * Pitch is always the same as bytes per line (for these video modes at least).
  */
 struct control_regvals {
-	int	pitch[3];		/* bytes/line, indexed by color_mode */
 	int	offset[3];		/* first pixel address */
 	unsigned regs[16];		/* for vswin .. reg10 */
 	unsigned char mode[3];		/* indexed by color_mode */
@@ -95,7 +118,6 @@
 
 /* Register values for 1280x1024, 75Hz mode (20) */
 static struct control_regvals control_reg_init_20 = {
-	{ 1280, 2560, 0 },
 	{ 0x10, 0x20, 0 },
 	{ 2129, 2128, 80, 42, 4, 2130, 2132, 88,
 	  420, 411, 91, 35, 421, 18, 211, 386, },
@@ -107,7 +129,6 @@
 
 /* Register values for 1280x960, 75Hz mode (19) */
 static struct control_regvals control_reg_init_19 = {
-	{ 1280, 2560, 0 },
 	{ 0x10, 0x20, 0 },
 	{ 1997, 1996, 76, 40, 4, 1998, 2000, 86,
 	  418, 409, 89, 35, 419, 18, 210, 384, },
@@ -119,7 +140,6 @@
 
 /* Register values for 1152x870, 75Hz mode (18) */
 static struct control_regvals control_reg_init_18 = {
-	{ 1152, 2304, 4608 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1825, 1822, 82, 43, 4, 1828, 1830, 120,
 	  726, 705, 129, 63, 727, 32, 364, 664 },
@@ -131,7 +151,6 @@
 
 /* Register values for 1024x768, 75Hz mode (17) */
 static struct control_regvals control_reg_init_17 = {
-	{ 1024, 2048, 4096 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1603, 1600, 64, 34, 4, 1606, 1608, 120,
 	  662, 641, 129, 47, 663, 24, 332, 616 },
@@ -141,9 +160,8 @@
 	1024, 768
 };
 
-/* Register values for 1024x768, 72Hz mode (16 (15?)) */
-static struct control_regvals control_reg_init_16 = {
-	{ 1024, 2048, 4096 },
+/* Register values for 1024x768, 72Hz mode 16 (15?) */
+static struct control_regvals control_reg_init_15 = {
 	{ 0x10, 0x28, 0x50 },
 	{ 1607, 1604, 68, 39, 10, 1610, 1612, 132,
 	  670, 653, 141, 67, 671, 34, 336, 604, },
@@ -155,7 +173,6 @@
 
 /* Register values for 1024x768, 60Hz mode (14) */
 static struct control_regvals control_reg_init_14 = {
-	{ 1024, 2048, 4096 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1607, 1604, 68, 39, 10, 1610, 1612, 132,
 	  670, 653, 141, 67, 671, 34, 336, 604, },
@@ -167,7 +184,6 @@
 
 /* Register values for 832x624, 75Hz mode (13) */
 static struct control_regvals control_reg_init_13 = {
-	{ 832, 1664, 3328 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1331, 1330, 82, 43, 4, 1332, 1334, 128,
 	  574, 553, 137, 31, 575, 16, 288, 544 },
@@ -178,7 +194,6 @@
 
 /* Register values for 800x600, 75Hz mode (12) */
 static struct control_regvals control_reg_init_12 = {
-	{ 800, 1600, 3200 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1247, 1246, 46, 25, 4, 1248, 1250, 104,
 	  526, 513, 113, 39, 527, 20, 264, 488, },
@@ -189,7 +204,6 @@
 
 /* Register values for 800x600, 72Hz mode (11) */
 static struct control_regvals control_reg_init_11 = {
-	{ 800, 1600, 3200 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1293, 1256, 56, 33, 10, 1330, 1332, 76,
 	  518, 485, 85, 59, 519, 30, 260, 460, },
@@ -200,7 +214,6 @@
 
 /* Register values for 800x600, 60Hz mode (10) */
 static struct control_regvals control_reg_init_10 = {
-	{ 800, 1600, 3200 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1293, 1256, 56, 33, 10, 1330, 1332, 76,
 	  518, 485, 85, 59, 519, 30, 260, 460, },
@@ -211,7 +224,6 @@
 
 /* Register values for 640x870, 75Hz Full Page Display (7) */
 static struct control_regvals control_reg_init_7 = {
-        { 640, 1280, 2560 },
 	{ 0x10, 0x30, 0x68 },
 	{ 0x727, 0x724, 0x58, 0x2e, 0x4, 0x72a, 0x72c, 0x40,
 	  0x19e, 0x18c, 0x4c, 0x27, 0x19f, 0x14, 0xd0, 0x178 },
@@ -222,7 +234,6 @@
 
 /* Register values for 640x480, 67Hz mode (6) */
 static struct control_regvals control_reg_init_6 = {
-	{ 640, 1280, 2560 },
 	{ 0, 8, 0x10 },
 	{ 1045, 1042, 82, 43, 4, 1048, 1050, 72,
 	  430, 393, 73, 31, 431, 16, 216, 400 },
@@ -233,7 +244,6 @@
 
 /* Register values for 640x480, 60Hz mode (5) */
 static struct control_regvals control_reg_init_5 = {
-	{ 640, 1280, 2560 },
 	{ 0x10, 0x28, 0x50 },
 	{ 1037, 1026, 66, 34, 2, 1048, 1050, 56,
 	  398, 385, 65, 47, 399, 24, 200, 352, },
@@ -253,8 +263,8 @@
 	&control_reg_init_12,
 	&control_reg_init_13,
 	&control_reg_init_14,
-	&control_reg_init_16,
-	&control_reg_init_16,
+	&control_reg_init_15,
+	&control_reg_init_15,
 	&control_reg_init_17,
 	&control_reg_init_18,
 	&control_reg_init_19,
diff -u --recursive --new-file v2.1.131/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.1.131/linux/drivers/video/creatorfb.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/creatorfb.c	Mon Dec 21 14:48:04 1998
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.15 1998/09/04 15:43:40 jj Exp $
+/* $Id: creatorfb.c,v 1.16 1998/12/21 05:14:39 davem Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -123,7 +123,12 @@
 #define FFB_ROP_NEW                  0x83
 
 #define FFB_UCSR_FIFO_MASK     0x00000fff
+#define FFB_UCSR_FB_BUSY       0x01000000
 #define FFB_UCSR_RP_BUSY       0x02000000
+#define FFB_UCSR_ALL_BUSY      (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY)
+#define FFB_UCSR_READ_ERR      0x40000000
+#define FFB_UCSR_FIFO_OVFL     0x80000000
+#define FFB_UCSR_ALL_ERRORS    (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL)
 
 struct ffb_fbc {
 	/* Next vertex registers */
@@ -271,6 +276,30 @@
 	volatile u32	mer;
 };
 
+static __inline__ void FFBFifo(struct ffb_fbc *ffb, int n)
+{
+	int limit = 10000;
+
+	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);
+}
+
+static __inline__ void FFBWait(struct ffb_fbc *ffb)
+{
+	int limit = 10000;
+
+	do {
+		if((ffb->ucsr & FFB_UCSR_ALL_BUSY) == 0)
+			break;
+		if((ffb->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+			ffb->ucsr = FFB_UCSR_ALL_ERRORS;
+	} while(--limit > 0);
+}
+
 struct ffb_dac {
 	volatile u32	type;
 	volatile u32	value;
@@ -313,6 +342,7 @@
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 	int x, y, w, h;
 	
+	FFBFifo(fbc, 6);
 	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
 	fbc->drawop = FFB_DRAWOP_RECTANGLE;
 
@@ -330,6 +360,7 @@
 	fbc->bx = x + fb->x_margin;
 	fbc->bh = h;
 	fbc->bw = w;
+	FFBWait(fbc);
 }
 
 static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
@@ -337,15 +368,18 @@
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 
+	FFBFifo(fbc, 2);
 	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
 	fbc->drawop = FFB_DRAWOP_RECTANGLE;
 	while (count-- > 0) {
+		FFBFifo(fbc, 4);
 		fbc->by = boxes[1];
 		fbc->bx = boxes[0];
 		fbc->bh = boxes[3] - boxes[1];
 		fbc->bw = boxes[2] - boxes[0];
 		boxes += 4;
 	}
+	FFBWait(fbc);
 }
 
 static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
@@ -370,11 +404,13 @@
 		xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
 	else
 		xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
+	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;
 	fbc->fontxy = xy;
+	FFBFifo(fbc, fontheight(p));
 	if (fontwidth(p) <= 8) {
 		for (i = 0; i < fontheight(p); i++)
 			fbc->font = *fd++ << 24;
@@ -384,6 +420,7 @@
 			fd += 2;
 		}
 	}
+	FFBWait(fbc);
 }
 
 static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -394,6 +431,7 @@
 	int i, xy;
 	u8 *fd1, *fd2, *fd3, *fd4;
 
+	FFBFifo(fbc, 2);
 	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
 	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
 	xy = fb->s.ffb.xy_margin;
@@ -408,6 +446,7 @@
 	if (fontwidth(p) <= 8) {
 		while (count >= 4) {
 			count -= 4;
+			FFBFifo(fbc, 3);
 			fbc->fontw = 4 * fontwidth(p);
 			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
@@ -422,6 +461,7 @@
 				fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
 				fd4 = p->fontdata + ((*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++) 
@@ -437,6 +477,7 @@
 	} else {
 		while (count >= 2) {
 			count -= 2;
+			FFBFifo(fbc, 3);
 			fbc->fontw = 2 * fontwidth(p);
 			fbc->fontinc = 0x10000;
 			fbc->fontxy = xy;
@@ -447,6 +488,7 @@
 				fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
 				fd2 = p->fontdata + (((*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;
@@ -456,6 +498,7 @@
 	}
 	while (count) {
 		count--;
+		FFBFifo(fbc, 3);
 		fbc->fontw = fontwidth(p);
 		fbc->fontinc = 0x10000;
 		fbc->fontxy = xy;
@@ -463,6 +506,7 @@
 			i = ((*s++ & p->charmask) << fontheightlog(p));
 		else
 			i = ((*s++ & p->charmask) * fontheight(p));
+		FFBFifo(fbc, fontheight(p));
 		if (fontwidth(p) <= 8) {
 			fd1 = p->fontdata + i;
 			for (i = 0; i < fontheight(p); i++)
@@ -476,6 +520,7 @@
 		}
 		xy += fontwidth(p);
 	}
+	FFBWait(fbc);
 }
 
 static void ffb_revc(struct display *p, int xx, int yy)
@@ -573,10 +618,12 @@
 {
 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
 
+	FFBFifo(fbc, 4);
 	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->pmask = 0xffffffff;
+	FFBWait(fbc);
 }                                
 
 static char idstring[60] __initdata = { 0 };
@@ -625,6 +672,12 @@
 	fb->switch_from_graph = ffb_switch_from_graph;
 	fb->fill = ffb_fill;
 	
+	/* If there are any read errors or fifo overflow conditions,
+	 * clear them now.
+	 */
+	if((fb->s.ffb.fbc->ucsr & FFB_UCSR_ALL_ERRORS) != 0)
+		fb->s.ffb.fbc->ucsr = FFB_UCSR_ALL_ERRORS;
+
 	ffb_switch_from_graph(fb);
 	
 	fb->physbase = regs[0].phys_addr;
diff -u --recursive --new-file v2.1.131/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.1.131/linux/drivers/video/cyberfb.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/cyberfb.c	Mon Dec 21 14:48:04 1998
@@ -166,6 +166,8 @@
 static unsigned long CyberMem;
 static unsigned long CyberSize;
 static volatile char *CyberRegs;
+static unsigned long CyberMem_phys;
+static unsigned long CyberRegs_phys;
 /* From cvision.c  for cvision_core.c */
 static unsigned long cv64_mem;
 static unsigned long cv64_fbmem;
@@ -428,9 +430,9 @@
 	DPRINTK("ENTER\n");
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 	strcpy(fix->id, cyberfb_name);
-	fix->smem_start = (char*) virt_to_phys ((void *)CyberMem);
+	fix->smem_start = (char*) CyberMem_phys;
 	fix->smem_len = CyberSize;
-	fix->mmio_start = (char*) virt_to_phys ((void *)CyberRegs);
+	fix->mmio_start = (char*) CyberRegs_phys;
 	fix->mmio_len = 0x10000;
 
 	fix->type = FB_TYPE_PACKED_PIXELS;
@@ -1153,6 +1155,8 @@
 
 	CyberMem = cv64_fbmem;
 	CyberRegs = cv64_regs;
+	CyberMem_phys = board_addr + 0x01400000;
+	CyberRegs_phys = CyberMem_phys + 0x00c00000;
 	DPRINTK("CyberMem=%08lx CyberRegs=%08lx\n", CyberMem,
 		(long unsigned int)CyberRegs);
 
@@ -1453,7 +1457,7 @@
 /* -------------------- Hardware specific routines ------------------------- */
 #if 0
 /* ARB Generates 100 usec delay */
-inline void __delay (unsigned long usecs)
+inline void __cv_delay (unsigned long usecs)
 {
 	int k;
 	
@@ -1493,7 +1497,7 @@
 {
 	vgaw (board, ACT_ADDRESS_W, idx);
 	udelay(100);
-	/* __delay (0); */
+	/* __cv_delay (0); */
 	return (vgar (board, ACT_ADDRESS_R));
 }
 
@@ -1895,7 +1899,7 @@
   vgaw16 (cv64_regs, ECR_BKGD_MIX, 0x07);
   vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x1000);
   udelay(200);
-  /* __delay (200000); */
+  /* __cv_delay (200000); */
   vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x2000);
   Cyber_WaitBlit();
   /* GfxBusyWait (cv64_regs); */
@@ -1903,7 +1907,7 @@
   Cyber_WaitBlit();
   /* GfxBusyWait (cv64_regs); */
   udelay(200);
-  /* __delay (200000); */
+  /* __cv_delay (200000); */
   vgaw16 (cv64_regs, ECR_READ_REG_DATA, 0x4FFF);
   Cyber_WaitBlit();
   /* GfxBusyWait (cv64_regs); */
@@ -1961,7 +1965,9 @@
   int xres, hfront, hsync, hback;
   int yres, vfront, vsync, vback;
   int bpp;
+#if 0
   float freq_f;
+#endif
   long freq;
   /* ---------------- */
 	
@@ -2066,9 +2072,15 @@
   /* cv64_compute_clock accepts arguments in Hz */
   /* pixclock is in ps ... convert to Hz */
 	
+#if 0
   freq_f = (1.0 / (float) video_mode->pixclock) * 1000000000;
   freq = ((long) freq_f) * 1000;
-	
+#else
+/* freq = (long) ((long long)1000000000000 / (long long) video_mode->pixclock);
+ */
+  freq = (1000000000 / video_mode->pixclock) * 1000;
+#endif
+
   mnr = cv64_compute_clock (freq);
   WSeq (cv64_regs, SEQ_ID_DCLK_HI, ((mnr & 0xFF00) >> 8));
   WSeq (cv64_regs, SEQ_ID_DCLK_LO, (mnr & 0xFF));
@@ -2257,14 +2269,14 @@
   WCrt (cv64_regs, CRT_ID_EXT_SYS_CNTL_1, cr50);
 	
   udelay(100);
-  /* __delay (100000); */
+  /* __cv_delay (100000); */
   WAttr (cv64_regs, ACT_ID_ATTR_MODE_CNTL, (TEXT ? 0x08 : 0x41));
   udelay(100);
-  /* __delay (100000); */
+  /* __cv_delay (100000); */
   WAttr (cv64_regs, ACT_ID_COLOR_PLANE_ENA,
 	 (video_mode->bits_per_pixel == 1) ? 0x01 : 0x0F);
   udelay(100);
-  /* __delay (100000); */
+  /* __cv_delay (100000); */
 	
   tfillm = (96 * (cv64_memclk / 1000)) / 240000;
 	
@@ -2296,7 +2308,7 @@
   WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_2, m);
   WCrt (cv64_regs, CRT_ID_EXT_MEM_CNTL_3, n);
   udelay(10);
-  /* __delay (10000); */
+  /* __cv_delay (10000); */
 	
   /* Text initialization */
 	
diff -u --recursive --new-file v2.1.131/linux/drivers/video/cyberfb.h linux/drivers/video/cyberfb.h
--- v2.1.131/linux/drivers/video/cyberfb.h	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/cyberfb.h	Mon Dec 21 14:48:04 1998
@@ -421,7 +421,7 @@
      /* --------------------------------- */
 
 /* in cvision_core.c */
-inline void __delay(unsigned long usecs);
+inline void __cv_delay(unsigned long usecs);
 inline void GfxBusyWait(volatile caddr_t board);
 inline void GfxFifoWait(volatile caddr_t board);
 inline unsigned char RAttr(volatile caddr_t board, short idx);
diff -u --recursive --new-file v2.1.131/linux/drivers/video/fbcon-cfb8.c linux/drivers/video/fbcon-cfb8.c
--- v2.1.131/linux/drivers/video/fbcon-cfb8.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/fbcon-cfb8.c	Mon Dec 21 14:48:04 1998
@@ -143,12 +143,12 @@
     case 12:
     case 16:
 	for (rows = fontheight(p) ; rows-- ; dest += bytes) {
-	    ((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
-	    ((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
-	    ((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
+	    ((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
+	    ((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+	    ((u32 *)dest)[2]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
 	    if (fontwidth(p) == 16)
 	        ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
-	    cdat += 2;
+	    cdat++;
         }
         break;
     }
@@ -200,12 +200,12 @@
 	    cdat = p->fontdata + (c * fontheight(p) << 1);
 
 	    for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
-		((u32 *)dest)[0]= (nibbletab_cfb8[*(u16 *)cdat >> 12] & eorx) ^ bgx;
-		((u32 *)dest)[1]= (nibbletab_cfb8[(*(u16 *)cdat >> 8) & 0xf] & eorx) ^ bgx;
-		((u32 *)dest)[2]= (nibbletab_cfb8[(*(u16 *)cdat >> 4) & 0xf] & eorx) ^ bgx;
+		((u32 *)dest)[0]= (nibbletab_cfb8[*cdat >> 4] & eorx) ^ bgx;
+		((u32 *)dest)[1]= (nibbletab_cfb8[*cdat++ & 0xf] & eorx) ^ bgx;
+		((u32 *)dest)[2]= (nibbletab_cfb8[(*cdat >> 4) & 0xf] & eorx) ^ bgx;
 		if (fontwidth(p) == 16)
 		    ((u32 *)dest)[3]= (nibbletab_cfb8[*cdat & 0xf] & eorx) ^ bgx;
-		cdat += 2;
+		cdat++;
 	    }
 	    dest0+=fontwidth(p);
         }
diff -u --recursive --new-file v2.1.131/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.1.131/linux/drivers/video/fbcon.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/fbcon.c	Mon Dec 21 14:48:04 1998
@@ -944,7 +944,8 @@
 {
     int unit = conp->vc_num;
     struct display *p = &fb_display[unit];
-    int is_txt = (p->type == FB_TYPE_TEXT);
+    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;
@@ -962,22 +963,34 @@
 
     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;
 	    switch (p->scrollmode & __SCROLL_YMASK) {
 	    case __SCROLL_YMOVE:
-		p->dispsw->bmove(p, t+count, 0, t, 0, b-t-count,
+	        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,
 				 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 > 3*conp->vc_rows>>2) {
+		if (b-t-count > 2*conp->vc_rows/3) {
 		    if (t > 0)
-			fbcon_bmove(conp, 0, 0, count, 0, t,
-				    conp->vc_cols);
-			ywrap_up(unit, conp, p, count);
+			fbcon_bmove(conp, 0, logos_left, count, logos_left, t, logos_width);
+		    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);
@@ -990,11 +1003,11 @@
 		break;
 
 	    case __SCROLL_YPAN:
-		if (( is_txt && (b-t == conp->vc_rows)) ||
-		    (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
+		if (( !scroll_partial && (b-t == conp->vc_rows)) ||
+		    ( scroll_partial  && (b-t-count > 3*conp->vc_rows>>2))) {
 		    if (t > 0)
-			fbcon_bmove(conp, 0, 0, count, 0, t,
-				    conp->vc_cols);
+			fbcon_bmove(conp, 0, logos_left, count, logos_left, t,
+				    logos_width);
 		    ypan_up(unit, conp, p, count);
 		    if (conp->vc_rows-b > 0)
 			fbcon_bmove(conp, b-count, 0, b, 0,
@@ -1049,8 +1062,8 @@
 		break;
 
 	    case __SCROLL_YPAN:
-		if (( is_txt && (b-t == conp->vc_rows)) ||
-		    (!is_txt && (b-t-count > 3*conp->vc_rows>>2))) {
+		if (( !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);
@@ -1250,46 +1263,41 @@
     if (!op->data) return 0;
     
     if (op->width <= 8) {
+	j = fontheight(p);
     	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < fontheight(p); j++)
-		*data++ = *fontdata++;
-	    memset(data, 0, 32-j);
-	    data += 32 - j;
+	    memcpy(data, fontdata, j);
+	    memset(data+j, 0, 32-j);
+	    data += 32;
+	    fontdata += j;
 	}
     }
 #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
     else if (op->width <= 16) {
+	j = fontheight(p) * 2;
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < fontheight(p); j++) {
-		*data++ = *(u16 *)fontdata >> 8;
-		*data++ = *(u16 *)fontdata;
-		fontdata += sizeof(u16);
-	    }
-	    memset(data, 0, 2*(32-j));
-	    data += 2 * (32 - j);
+	    memcpy(data, fontdata, j);
+	    memset(data+j, 0, 64-j);
+	    data += 64;
+	    fontdata += j;
 	}
     } else if (op->width <= 24) {
 	for (i = 0; i < op->charcount; i++) {
 	    for (j = 0; j < fontheight(p); j++) {
-		*data++ = *(u32 *)fontdata >> 24;
-		*data++ = *(u32 *)fontdata >> 16;
-		*data++ = *(u32 *)fontdata >> 8;
+		*data++ = fontdata[0];
+		*data++ = fontdata[1];
+		*data++ = fontdata[2];
 		fontdata += sizeof(u32);
 	    }
 	    memset(data, 0, 3*(32-j));
 	    data += 3 * (32 - j);
 	}
     } else {
+	j = fontheight(p) * 4;
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < fontheight(p); j++) {
-		*data++ = *(u32 *)fontdata >> 24;
-		*data++ = *(u32 *)fontdata >> 16;
-		*data++ = *(u32 *)fontdata >> 8;
-		*data++ = *(u32 *)fontdata;
-		fontdata += sizeof(u32);
-	    }
-	    memset(data, 0, 4*(32-j));
-	    data += 4 * (32 - j);
+	    memcpy(data, fontdata, j);
+	    memset(data+j, 0, 128-j);
+	    data += 128;
+	    fontdata += j;
 	}
     }
 #endif
@@ -1329,12 +1337,44 @@
     	p->fgshift--;
     	p->bgshift--;
     	p->charmask = 0xff;
+
+	/* ++Edmund: reorder the attribute bits */
+	{
+	    struct vc_data *conp = p->conp;
+	    unsigned short *cp = (unsigned short *) conp->vc_origin;
+	    int count = conp->vc_screenbuf_size/2;
+	    unsigned short c;
+	    for (; count > 0; count--, cp++) {
+	        c = scr_readw(cp);
+		scr_writew(((c & 0xfe00) >> 1) | (c & 0xff), cp);
+	    }
+	    c = conp->vc_video_erase_char;
+	    conp->vc_video_erase_char = ((c & 0xfe00) >> 1) | (c & 0xff);
+	    conp->vc_attr >>= 1;
+	}
+
     } else if (!p->conp->vc_hi_font_mask && cnt == 512) {
     	p->conp->vc_hi_font_mask = 0x100;
     	p->conp->vc_complement_mask <<= 1;
     	p->fgshift++;
     	p->bgshift++;
     	p->charmask = 0x1ff;
+
+	/* ++Edmund: reorder the attribute bits */
+	{
+	    struct vc_data *conp = p->conp;
+	    unsigned short *cp = (unsigned short *) conp->vc_origin;
+	    int count = conp->vc_screenbuf_size/2;
+	    unsigned short c;
+	    for (; count > 0; count--, cp++) {
+	        c = scr_readw(cp);
+		scr_writew(((c & 0xff00) << 1) | (c & 0xff), cp);
+	    }
+	    c = conp->vc_video_erase_char;
+	    conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff);
+	    conp->vc_attr <<= 1;
+	}
+
     }
     fbcon_font_widths(p);
 
@@ -1381,16 +1421,13 @@
     int h = op->height;
     int size = h;
     int i, j, k;
-    u8 *new_data, *data = op->data, c, *p;
-#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
-    u32 d;
-#else
+    u8 *new_data, *data = op->data, *p;
 
+#ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
     if (w != 8)
     	return -EINVAL;
 #endif
-
-    if (w > 32 || (op->charcount != 256 && op->charcount != 512))
+    if ((w <= 0) || (w > 32) || (op->charcount != 256 && op->charcount != 512))
         return -EINVAL;
     
     if (w > 8) { 
@@ -1407,56 +1444,46 @@
     FNTSIZE(new_data) = size;
     FNTCHARCNT(new_data) = op->charcount;
     REFCOUNT(new_data) = 0; /* usage counter */
-    k = 0;
     p = new_data;
     if (w <= 8) {
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < h; j++) {
-	        c = *data++;
-		k += c;
-		*p++ = c;
-	    }
-	    data += 32 - h;
+	    memcpy(p, data, h);
+	    data += 32;
+	    p += h;
 	}
     }
 #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
     else if (w <= 16) {
+	h *= 2;
 	for (i = 0; i < op->charcount; i++) {
-	    for (j = 0; j < h; j++) {
-	        d = (data[0] << 8) | data[1];
-	        data += 2;
-		k += d;
-		*(u16 *)p = d;
-		p += sizeof(u16);
-	    }
-	    data += 2*(32 - h);
+	    memcpy(p, data, h);
+	    data += 64;
+	    p += h;
 	}
-    } else {
+    } else if (w <= 24) {
 	for (i = 0; i < op->charcount; i++) {
 	    for (j = 0; j < h; j++) {
-	    	if (w <= 24) {
-		    d = (data[0] << 24) | 
-			(data[1] << 16) | 
-			(data[2] << 8);
-		    data += 3;
-		} else {
-		    d = (data[0] << 24) | 
-			(data[1] << 16) | 
-			(data[2] << 8) |
-			data[3];
-		    data += 4;
-		}
-		k += d;
-		*(u32 *)p = d;
+	        memcpy(p, data, 3);
+		p[3] = 0;
+		data += 3;
 		p += sizeof(u32);
 	    }
-	    if (w <= 24)
-		data += 3*(32 - h);
-	    else
-		data += 4*(32 - h);
+	    data += 3*(32 - h);
+	}
+    } else {
+	h *= 4;
+	for (i = 0; i < op->charcount; i++) {
+	    memcpy(p, data, h);
+	    data += 128;
+	    p += h;
 	}
     }
 #endif
+    /* we can do it in u32 chunks because of charcount is 256 or 512, so
+       font length must be multiple of 256, at least. And 256 is multiple
+       of 4 */
+    k = 0;
+    while (p > new_data) k += *--(u32 *)p;
     FNTSUM(new_data) = k;
     /* Check if the same font is on some other console already */
     for (i = 0; i < MAX_NR_CONSOLES; i++) {
@@ -1587,7 +1614,7 @@
     p->var.xoffset = 0;
     p->var.yoffset = offset*fontheight(p);
     p->fb_info->updatevar(unit, p->fb_info);
-    if (!offset)
+    if (!scrollback_current)
 	fbcon_cursor(conp, CM_DRAW);
     return 0;
 }
@@ -1664,8 +1691,8 @@
 	logo_depth = 1;
     }
 
-    for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&
-    	 x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
+    for (x = p->var.xres - LOGO_W; x > 0 && x > (int)p->var.xres 
+        - smp_num_cpus * (LOGO_W + 8); x -= (LOGO_W + 8)) {
     	 
 #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \
     defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)
@@ -1766,6 +1793,20 @@
 		}
 	    }
 	    done = 1;
+	}
+#endif
+#if defined(CONFIG_FBCON_CFB4)
+	if (depth == 4 && p->type == FB_TYPE_PACKED_PIXELS) {
+		src = logo;
+		for( y1 = 0; y1 < LOGO_H; y1++) {
+			dst = fb + y1*line + x/2;
+			for( x1 = 0; x1 < LOGO_W/2; x1++) {
+				u8 q = *src++;
+				q = (q << 4) | (q >> 4);
+				*dst++ = q;
+			}
+		}
+		done = 1;
 	}
 #endif
 #if defined(CONFIG_FBCON_CFB8) || defined(CONFIG_FB_SBUS)
diff -u --recursive --new-file v2.1.131/linux/drivers/video/font_sun12x22.c linux/drivers/video/font_sun12x22.c
--- v2.1.131/linux/drivers/video/font_sun12x22.c	Mon Oct  5 13:13:41 1998
+++ linux/drivers/video/font_sun12x22.c	Mon Dec 21 14:48:04 1998
@@ -1,6207 +1,6207 @@
 #include <video/font.h>
 
-#define FONTDATAMAX 5632
+#define FONTDATAMAX 11264
 
-static unsigned short fontdata_sun12x22[FONTDATAMAX] = {
+static unsigned char fontdata_sun12x22[FONTDATAMAX] = {
 
 	/* 0 0x00 '^@' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 1 0x01 '^A' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 2 0x02 '^B' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 3 0x03 '^C' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 4 0x04 '^D' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 5 0x05 '^E' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 6 0x06 '^F' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 7 0x07 '^G' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 8 0x08 '^H' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 9 0x09 '^I' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 10 0x0a '^J' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 11 0x0b '^K' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 12 0x0c '^L' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 13 0x0d '^M' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 14 0x0e '^N' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 15 0x0f '^O' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 16 0x10 '^P' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 17 0x11 '^Q' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 18 0x12 '^R' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 19 0x13 '^S' */
-	0x0000, /* 000000000000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 20 0x14 '^T' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1ff0, /* 000111111111 */
-	0x3cc0, /* 001111001100 */
-	0x7cc0, /* 011111001100 */
-	0x7cc0, /* 011111001100 */
-	0x7cc0, /* 011111001100 */
-	0x3cc0, /* 001111001100 */
-	0x1cc0, /* 000111001100 */
-	0x0cc0, /* 000011001100 */
-	0x0cc0, /* 000011001100 */
-	0x0cc0, /* 000011001100 */
-	0x0cc0, /* 000011001100 */
-	0x0cc0, /* 000011001100 */
-	0x0cc0, /* 000011001100 */
-	0x1ce0, /* 000111001110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xf0, /* 000111111111 */
+	0x3c, 0xc0, /* 001111001100 */
+	0x7c, 0xc0, /* 011111001100 */
+	0x7c, 0xc0, /* 011111001100 */
+	0x7c, 0xc0, /* 011111001100 */
+	0x3c, 0xc0, /* 001111001100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x1c, 0xe0, /* 000111001110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 21 0x15 '^U' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f00, /* 000111110000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x1f00, /* 000111110000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x1f00, /* 000111110000 */
-	0x0180, /* 000000011000 */
-	0x0180, /* 000000011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 22 0x16 '^V' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 23 0x17 '^W' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 24 0x18 '^X' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 25 0x19 '^Y' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 26 0x1a '^Z' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 27 0x1b '^[' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 28 0x1c '^\' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 29 0x1d '^]' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 30 0x1e '^^' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 31 0x1f '^_' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 32 0x20 ' ' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 33 0x21 '!' */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 34 0x22 '"' */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 35 0x23 '#' */
-	0x0000, /* 000000000000 */
-	0x0330, /* 000000110011 */
-	0x0330, /* 000000110011 */
-	0x0330, /* 000000110011 */
-	0x0660, /* 000001100110 */
-	0x1ff0, /* 000111111111 */
-	0x1ff0, /* 000111111111 */
-	0x0cc0, /* 000011001100 */
-	0x0cc0, /* 000011001100 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x7fc0, /* 011111111100 */
-	0x7fc0, /* 011111111100 */
-	0x3300, /* 001100110000 */
-	0x6600, /* 011001100000 */
-	0x6600, /* 011001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0x30, /* 000000110011 */
+	0x03, 0x30, /* 000000110011 */
+	0x03, 0x30, /* 000000110011 */
+	0x06, 0x60, /* 000001100110 */
+	0x1f, 0xf0, /* 000111111111 */
+	0x1f, 0xf0, /* 000111111111 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x33, 0x00, /* 001100110000 */
+	0x66, 0x00, /* 011001100000 */
+	0x66, 0x00, /* 011001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 36 0x24 '$' */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x3fc0, /* 001111111100 */
-	0x66e0, /* 011001101110 */
-	0x6660, /* 011001100110 */
-	0x6600, /* 011001100000 */
-	0x3e00, /* 001111100000 */
-	0x1f80, /* 000111111000 */
-	0x07c0, /* 000001111100 */
-	0x0660, /* 000001100110 */
-	0x0660, /* 000001100110 */
-	0x6660, /* 011001100110 */
-	0x7fc0, /* 011111111100 */
-	0x3f80, /* 001111111000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x66, 0xe0, /* 011001101110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x00, /* 011001100000 */
+	0x3e, 0x00, /* 001111100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x07, 0xc0, /* 000001111100 */
+	0x06, 0x60, /* 000001100110 */
+	0x06, 0x60, /* 000001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 37 0x25 '%' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x38c0, /* 001110001100 */
-	0x4cc0, /* 010011001100 */
-	0x4580, /* 010001011000 */
-	0x6580, /* 011001011000 */
-	0x3b00, /* 001110110000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x0dc0, /* 000011011100 */
-	0x1a60, /* 000110100110 */
-	0x1a20, /* 000110100010 */
-	0x3320, /* 001100110010 */
-	0x31c0, /* 001100011100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x38, 0xc0, /* 001110001100 */
+	0x4c, 0xc0, /* 010011001100 */
+	0x45, 0x80, /* 010001011000 */
+	0x65, 0x80, /* 011001011000 */
+	0x3b, 0x00, /* 001110110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0d, 0xc0, /* 000011011100 */
+	0x1a, 0x60, /* 000110100110 */
+	0x1a, 0x20, /* 000110100010 */
+	0x33, 0x20, /* 001100110010 */
+	0x31, 0xc0, /* 001100011100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 38 0x26 '&' */
-	0x0000, /* 000000000000 */
-	0x0700, /* 000001110000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x18c0, /* 000110001100 */
-	0x18c0, /* 000110001100 */
-	0x0f80, /* 000011111000 */
-	0x1e00, /* 000111100000 */
-	0x3e00, /* 001111100000 */
-	0x7700, /* 011101110000 */
-	0x6360, /* 011000110110 */
-	0x61e0, /* 011000011110 */
-	0x61c0, /* 011000011100 */
-	0x6180, /* 011000011000 */
-	0x3fe0, /* 001111111110 */
-	0x1e60, /* 000111100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x0f, 0x80, /* 000011111000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x3e, 0x00, /* 001111100000 */
+	0x77, 0x00, /* 011101110000 */
+	0x63, 0x60, /* 011000110110 */
+	0x61, 0xe0, /* 011000011110 */
+	0x61, 0xc0, /* 011000011100 */
+	0x61, 0x80, /* 011000011000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 39 0x27 ''' */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x1000, /* 000100000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 40 0x28 '(' */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0180, /* 000000011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x01, 0x80, /* 000000011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 41 0x29 ')' */
-	0x0000, /* 000000000000 */
-	0x1800, /* 000110000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 42 0x2a '*' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x0600, /* 000001100000 */
-	0x6660, /* 011001100110 */
-	0x76e0, /* 011101101110 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x76e0, /* 011101101110 */
-	0x6660, /* 011001100110 */
-	0x0600, /* 000001100000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x66, 0x60, /* 011001100110 */
+	0x76, 0xe0, /* 011101101110 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x76, 0xe0, /* 011101101110 */
+	0x66, 0x60, /* 011001100110 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 43 0x2b '+' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 44 0x2c ',' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x1000, /* 000100000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 45 0x2d '-' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 46 0x2e '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0c00, /* 000011000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 47 0x2f '/' */
-	0x0000, /* 000000000000 */
-	0x0060, /* 000000000110 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0180, /* 000000011000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x6000, /* 011000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 48 0x30 '0' */
-	0x0000, /* 000000000000 */
-	0x0700, /* 000001110000 */
-	0x0f80, /* 000011111000 */
-	0x1180, /* 000100011000 */
-	0x10c0, /* 000100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x3080, /* 001100001000 */
-	0x1880, /* 000110001000 */
-	0x1f00, /* 000111110000 */
-	0x0e00, /* 000011100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0x80, /* 000100011000 */
+	0x10, 0xc0, /* 000100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0x80, /* 001100001000 */
+	0x18, 0x80, /* 000110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 49 0x31 '1' */
-	0x0000, /* 000000000000 */
-	0x0200, /* 000000100000 */
-	0x0600, /* 000001100000 */
-	0x0e00, /* 000011100000 */
-	0x1e00, /* 000111100000 */
-	0x3600, /* 001101100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x36, 0x00, /* 001101100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 50 0x32 '2' */
-	0x0000, /* 000000000000 */
-	0x1f00, /* 000111110000 */
-	0x3f80, /* 001111111000 */
-	0x61c0, /* 011000011100 */
-	0x40c0, /* 010000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x3020, /* 001100000010 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x61, 0xc0, /* 011000011100 */
+	0x40, 0xc0, /* 010000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x30, 0x20, /* 001100000010 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 51 0x33 '3' */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x1fc0, /* 000111111100 */
-	0x20e0, /* 001000001110 */
-	0x4060, /* 010000000110 */
-	0x0060, /* 000000000110 */
-	0x00e0, /* 000000001110 */
-	0x07c0, /* 000001111100 */
-	0x0fc0, /* 000011111100 */
-	0x00e0, /* 000000001110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x4060, /* 010000000110 */
-	0x6040, /* 011000000100 */
-	0x3f80, /* 001111111000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x40, 0x60, /* 010000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0xe0, /* 000000001110 */
+	0x07, 0xc0, /* 000001111100 */
+	0x0f, 0xc0, /* 000011111100 */
+	0x00, 0xe0, /* 000000001110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x40, 0x60, /* 010000000110 */
+	0x60, 0x40, /* 011000000100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 52 0x34 '4' */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0380, /* 000000111000 */
-	0x0380, /* 000000111000 */
-	0x0580, /* 000001011000 */
-	0x0580, /* 000001011000 */
-	0x0980, /* 000010011000 */
-	0x0980, /* 000010011000 */
-	0x1180, /* 000100011000 */
-	0x1180, /* 000100011000 */
-	0x2180, /* 001000011000 */
-	0x3fe0, /* 001111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0180, /* 000000011000 */
-	0x0180, /* 000000011000 */
-	0x0180, /* 000000011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x80, /* 000000111000 */
+	0x03, 0x80, /* 000000111000 */
+	0x05, 0x80, /* 000001011000 */
+	0x05, 0x80, /* 000001011000 */
+	0x09, 0x80, /* 000010011000 */
+	0x09, 0x80, /* 000010011000 */
+	0x11, 0x80, /* 000100011000 */
+	0x11, 0x80, /* 000100011000 */
+	0x21, 0x80, /* 001000011000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 53 0x35 '5' */
-	0x0000, /* 000000000000 */
-	0x0fc0, /* 000011111100 */
-	0x0fc0, /* 000011111100 */
-	0x1000, /* 000100000000 */
-	0x1000, /* 000100000000 */
-	0x2000, /* 001000000000 */
-	0x3f80, /* 001111111000 */
-	0x31c0, /* 001100011100 */
-	0x00e0, /* 000000001110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x4060, /* 010000000110 */
-	0x6060, /* 011000000110 */
-	0x30c0, /* 001100001100 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xc0, /* 000011111100 */
+	0x0f, 0xc0, /* 000011111100 */
+	0x10, 0x00, /* 000100000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x20, 0x00, /* 001000000000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x31, 0xc0, /* 001100011100 */
+	0x00, 0xe0, /* 000000001110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x40, 0x60, /* 010000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 54 0x36 '6' */
-	0x0000, /* 000000000000 */
-	0x0700, /* 000001110000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x6000, /* 011000000000 */
-	0x6780, /* 011001111000 */
-	0x6fc0, /* 011011111100 */
-	0x70e0, /* 011100001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7040, /* 011100000100 */
-	0x3f80, /* 001111111000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x67, 0x80, /* 011001111000 */
+	0x6f, 0xc0, /* 011011111100 */
+	0x70, 0xe0, /* 011100001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 55 0x37 '7' */
-	0x0000, /* 000000000000 */
-	0x1fe0, /* 000111111110 */
-	0x3fe0, /* 001111111110 */
-	0x6040, /* 011000000100 */
-	0x0040, /* 000000000100 */
-	0x00c0, /* 000000001100 */
-	0x0080, /* 000000001000 */
-	0x0080, /* 000000001000 */
-	0x0180, /* 000000011000 */
-	0x0100, /* 000000010000 */
-	0x0100, /* 000000010000 */
-	0x0300, /* 000000110000 */
-	0x0200, /* 000000100000 */
-	0x0200, /* 000000100000 */
-	0x0600, /* 000001100000 */
-	0x0400, /* 000001000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x60, 0x40, /* 011000000100 */
+	0x00, 0x40, /* 000000000100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0x80, /* 000000001000 */
+	0x00, 0x80, /* 000000001000 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x00, /* 000000010000 */
+	0x01, 0x00, /* 000000010000 */
+	0x03, 0x00, /* 000000110000 */
+	0x02, 0x00, /* 000000100000 */
+	0x02, 0x00, /* 000000100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x04, 0x00, /* 000001000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 56 0x38 '8' */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x1180, /* 000100011000 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x1880, /* 000110001000 */
-	0x0d00, /* 000011010000 */
-	0x0600, /* 000001100000 */
-	0x0b00, /* 000010110000 */
-	0x1180, /* 000100011000 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x1880, /* 000110001000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x11, 0x80, /* 000100011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x18, 0x80, /* 000110001000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x11, 0x80, /* 000100011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x18, 0x80, /* 000110001000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 57 0x39 '9' */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x70e0, /* 011100001110 */
-	0x3f60, /* 001111110110 */
-	0x1e60, /* 000111100110 */
-	0x0060, /* 000000000110 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0180, /* 000000011000 */
-	0x0700, /* 000001110000 */
-	0x3c00, /* 001111000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0xe0, /* 011100001110 */
+	0x3f, 0x60, /* 001111110110 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0x80, /* 000000011000 */
+	0x07, 0x00, /* 000001110000 */
+	0x3c, 0x00, /* 001111000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 58 0x3a ':' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0c00, /* 000011000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0c00, /* 000011000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 59 0x3b ';' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0c00, /* 000011000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x1000, /* 000100000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 60 0x3c '<' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0060, /* 000000000110 */
-	0x01c0, /* 000000011100 */
-	0x0700, /* 000001110000 */
-	0x1c00, /* 000111000000 */
-	0x7000, /* 011100000000 */
-	0x7000, /* 011100000000 */
-	0x1c00, /* 000111000000 */
-	0x0700, /* 000001110000 */
-	0x01c0, /* 000000011100 */
-	0x0060, /* 000000000110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x60, /* 000000000110 */
+	0x01, 0xc0, /* 000000011100 */
+	0x07, 0x00, /* 000001110000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 61 0x3d '=' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 62 0x3e '>' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x6000, /* 011000000000 */
-	0x3800, /* 001110000000 */
-	0x0e00, /* 000011100000 */
-	0x0380, /* 000000111000 */
-	0x00e0, /* 000000001110 */
-	0x00e0, /* 000000001110 */
-	0x0380, /* 000000111000 */
-	0x0e00, /* 000011100000 */
-	0x3800, /* 001110000000 */
-	0x6000, /* 011000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x38, 0x00, /* 001110000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x03, 0x80, /* 000000111000 */
+	0x00, 0xe0, /* 000000001110 */
+	0x00, 0xe0, /* 000000001110 */
+	0x03, 0x80, /* 000000111000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x38, 0x00, /* 001110000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 63 0x3f '?' */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x1f80, /* 000111111000 */
-	0x39c0, /* 001110011100 */
-	0x20c0, /* 001000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x39, 0xc0, /* 001110011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 64 0x40 '@' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x3fc0, /* 001111111100 */
-	0x3060, /* 001100000110 */
-	0x6060, /* 011000000110 */
-	0x6720, /* 011001110010 */
-	0x6fa0, /* 011011111010 */
-	0x6ca0, /* 011011001010 */
-	0x6ca0, /* 011011001010 */
-	0x67e0, /* 011001111110 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x3fe0, /* 001111111110 */
-	0x0fe0, /* 000011111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x30, 0x60, /* 001100000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x67, 0x20, /* 011001110010 */
+	0x6f, 0xa0, /* 011011111010 */
+	0x6c, 0xa0, /* 011011001010 */
+	0x6c, 0xa0, /* 011011001010 */
+	0x67, 0xe0, /* 011001111110 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x0f, 0xe0, /* 000011111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 65 0x41 'A' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0b00, /* 000010110000 */
-	0x0b00, /* 000010110000 */
-	0x0900, /* 000010010000 */
-	0x1180, /* 000100011000 */
-	0x1180, /* 000100011000 */
-	0x1080, /* 000100001000 */
-	0x3fc0, /* 001111111100 */
-	0x20c0, /* 001000001100 */
-	0x2040, /* 001000000100 */
-	0x4060, /* 010000000110 */
-	0x4060, /* 010000000110 */
-	0xe0f0, /* 111000001111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x09, 0x00, /* 000010010000 */
+	0x11, 0x80, /* 000100011000 */
+	0x11, 0x80, /* 000100011000 */
+	0x10, 0x80, /* 000100001000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x20, 0x40, /* 001000000100 */
+	0x40, 0x60, /* 010000000110 */
+	0x40, 0x60, /* 010000000110 */
+	0xe0, 0xf0, /* 111000001111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 66 0x42 'B' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xff00, /* 111111110000 */
-	0x6080, /* 011000001000 */
-	0x60c0, /* 011000001100 */
-	0x60c0, /* 011000001100 */
-	0x60c0, /* 011000001100 */
-	0x6180, /* 011000011000 */
-	0x7f80, /* 011111111000 */
-	0x60c0, /* 011000001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x60c0, /* 011000001100 */
-	0xff80, /* 111111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0x00, /* 111111110000 */
+	0x60, 0x80, /* 011000001000 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x61, 0x80, /* 011000011000 */
+	0x7f, 0x80, /* 011111111000 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0xc0, /* 011000001100 */
+	0xff, 0x80, /* 111111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 67 0x43 'C' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0fc0, /* 000011111100 */
-	0x1060, /* 000100000110 */
-	0x2020, /* 001000000010 */
-	0x2000, /* 001000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x2000, /* 001000000000 */
-	0x3020, /* 001100000010 */
-	0x1840, /* 000110000100 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xc0, /* 000011111100 */
+	0x10, 0x60, /* 000100000110 */
+	0x20, 0x20, /* 001000000010 */
+	0x20, 0x00, /* 001000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x20, 0x00, /* 001000000000 */
+	0x30, 0x20, /* 001100000010 */
+	0x18, 0x40, /* 000110000100 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 68 0x44 'D' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xff00, /* 111111110000 */
-	0x61c0, /* 011000011100 */
-	0x60c0, /* 011000001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6040, /* 011000000100 */
-	0x6180, /* 011000011000 */
-	0xfe00, /* 111111100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0x00, /* 111111110000 */
+	0x61, 0xc0, /* 011000011100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x40, /* 011000000100 */
+	0x61, 0x80, /* 011000011000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 69 0x45 'E' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fc0, /* 011111111100 */
-	0x3040, /* 001100000100 */
-	0x3040, /* 001100000100 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3080, /* 001100001000 */
-	0x3f80, /* 001111111000 */
-	0x3080, /* 001100001000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3020, /* 001100000010 */
-	0x3020, /* 001100000010 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x80, /* 001100001000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x30, 0x80, /* 001100001000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x20, /* 001100000010 */
+	0x30, 0x20, /* 001100000010 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 70 0x46 'F' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fc0, /* 011111111100 */
-	0x3040, /* 001100000100 */
-	0x3040, /* 001100000100 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3080, /* 001100001000 */
-	0x3f80, /* 001111111000 */
-	0x3080, /* 001100001000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x7800, /* 011110000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x80, /* 001100001000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x30, 0x80, /* 001100001000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 71 0x47 'G' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0fc0, /* 000011111100 */
-	0x1060, /* 000100000110 */
-	0x2020, /* 001000000010 */
-	0x2000, /* 001000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x61f0, /* 011000011111 */
-	0x6060, /* 011000000110 */
-	0x2060, /* 001000000110 */
-	0x3060, /* 001100000110 */
-	0x1860, /* 000110000110 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xc0, /* 000011111100 */
+	0x10, 0x60, /* 000100000110 */
+	0x20, 0x20, /* 001000000010 */
+	0x20, 0x00, /* 001000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x61, 0xf0, /* 011000011111 */
+	0x60, 0x60, /* 011000000110 */
+	0x20, 0x60, /* 001000000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x18, 0x60, /* 000110000110 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 72 0x48 'H' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf0f0, /* 111100001111 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7fe0, /* 011111111110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0xf0f0, /* 111100001111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0xf0, /* 111100001111 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0xf0, 0xf0, /* 111100001111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 73 0x49 'I' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f80, /* 000111111000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 74 0x4a 'J' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f80, /* 000111111000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0400, /* 000001000000 */
-	0x3800, /* 001110000000 */
-	0x3000, /* 001100000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x04, 0x00, /* 000001000000 */
+	0x38, 0x00, /* 001110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 75 0x4b 'K' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf0e0, /* 111100001110 */
-	0x6180, /* 011000011000 */
-	0x6300, /* 011000110000 */
-	0x6600, /* 011001100000 */
-	0x6c00, /* 011011000000 */
-	0x7800, /* 011110000000 */
-	0x7800, /* 011110000000 */
-	0x7c00, /* 011111000000 */
-	0x6e00, /* 011011100000 */
-	0x6700, /* 011001110000 */
-	0x6380, /* 011000111000 */
-	0x61c0, /* 011000011100 */
-	0x60e0, /* 011000001110 */
-	0xf070, /* 111100000111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0xe0, /* 111100001110 */
+	0x61, 0x80, /* 011000011000 */
+	0x63, 0x00, /* 011000110000 */
+	0x66, 0x00, /* 011001100000 */
+	0x6c, 0x00, /* 011011000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x6e, 0x00, /* 011011100000 */
+	0x67, 0x00, /* 011001110000 */
+	0x63, 0x80, /* 011000111000 */
+	0x61, 0xc0, /* 011000011100 */
+	0x60, 0xe0, /* 011000001110 */
+	0xf0, 0x70, /* 111100000111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 76 0x4c 'L' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7800, /* 011110000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3020, /* 001100000010 */
-	0x3020, /* 001100000010 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x20, /* 001100000010 */
+	0x30, 0x20, /* 001100000010 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 77 0x4d 'M' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xe070, /* 111000000111 */
-	0x60e0, /* 011000001110 */
-	0x70e0, /* 011100001110 */
-	0x70e0, /* 011100001110 */
-	0x70e0, /* 011100001110 */
-	0x5960, /* 010110010110 */
-	0x5960, /* 010110010110 */
-	0x5960, /* 010110010110 */
-	0x4d60, /* 010011010110 */
-	0x4e60, /* 010011100110 */
-	0x4e60, /* 010011100110 */
-	0x4460, /* 010001000110 */
-	0x4460, /* 010001000110 */
-	0xe4f0, /* 111001001111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xe0, 0x70, /* 111000000111 */
+	0x60, 0xe0, /* 011000001110 */
+	0x70, 0xe0, /* 011100001110 */
+	0x70, 0xe0, /* 011100001110 */
+	0x70, 0xe0, /* 011100001110 */
+	0x59, 0x60, /* 010110010110 */
+	0x59, 0x60, /* 010110010110 */
+	0x59, 0x60, /* 010110010110 */
+	0x4d, 0x60, /* 010011010110 */
+	0x4e, 0x60, /* 010011100110 */
+	0x4e, 0x60, /* 010011100110 */
+	0x44, 0x60, /* 010001000110 */
+	0x44, 0x60, /* 010001000110 */
+	0xe4, 0xf0, /* 111001001111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 78 0x4e 'N' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xc070, /* 110000000111 */
-	0x6020, /* 011000000010 */
-	0x7020, /* 011100000010 */
-	0x7820, /* 011110000010 */
-	0x5820, /* 010110000010 */
-	0x4c20, /* 010011000010 */
-	0x4620, /* 010001100010 */
-	0x4720, /* 010001110010 */
-	0x4320, /* 010000110010 */
-	0x41a0, /* 010000011010 */
-	0x40e0, /* 010000001110 */
-	0x40e0, /* 010000001110 */
-	0x4060, /* 010000000110 */
-	0xe030, /* 111000000011 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xc0, 0x70, /* 110000000111 */
+	0x60, 0x20, /* 011000000010 */
+	0x70, 0x20, /* 011100000010 */
+	0x78, 0x20, /* 011110000010 */
+	0x58, 0x20, /* 010110000010 */
+	0x4c, 0x20, /* 010011000010 */
+	0x46, 0x20, /* 010001100010 */
+	0x47, 0x20, /* 010001110010 */
+	0x43, 0x20, /* 010000110010 */
+	0x41, 0xa0, /* 010000011010 */
+	0x40, 0xe0, /* 010000001110 */
+	0x40, 0xe0, /* 010000001110 */
+	0x40, 0x60, /* 010000000110 */
+	0xe0, 0x30, /* 111000000011 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 79 0x4f 'O' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x11c0, /* 000100011100 */
-	0x20c0, /* 001000001100 */
-	0x2060, /* 001000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x2040, /* 001000000100 */
-	0x3040, /* 001100000100 */
-	0x1880, /* 000110001000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x20, 0x60, /* 001000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x20, 0x40, /* 001000000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x18, 0x80, /* 000110001000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 80 0x50 'P' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7f80, /* 011111111000 */
-	0x30c0, /* 001100001100 */
-	0x3060, /* 001100000110 */
-	0x3060, /* 001100000110 */
-	0x3060, /* 001100000110 */
-	0x30c0, /* 001100001100 */
-	0x3780, /* 001101111000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x7800, /* 011110000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0x80, /* 011111111000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0x60, /* 001100000110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x37, 0x80, /* 001101111000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 81 0x51 'Q' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x11c0, /* 000100011100 */
-	0x20c0, /* 001000001100 */
-	0x2060, /* 001000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x3040, /* 001100000100 */
-	0x3840, /* 001110000100 */
-	0x1f80, /* 000111111000 */
-	0x0e00, /* 000011100000 */
-	0x1f00, /* 000111110000 */
-	0x2390, /* 001000111001 */
-	0x01e0, /* 000000011110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x20, 0x60, /* 001000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x30, 0x40, /* 001100000100 */
+	0x38, 0x40, /* 001110000100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x23, 0x90, /* 001000111001 */
+	0x01, 0xe0, /* 000000011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 82 0x52 'R' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xff00, /* 111111110000 */
-	0x6180, /* 011000011000 */
-	0x60c0, /* 011000001100 */
-	0x60c0, /* 011000001100 */
-	0x60c0, /* 011000001100 */
-	0x6080, /* 011000001000 */
-	0x7f00, /* 011111110000 */
-	0x7c00, /* 011111000000 */
-	0x6e00, /* 011011100000 */
-	0x6700, /* 011001110000 */
-	0x6380, /* 011000111000 */
-	0x61c0, /* 011000011100 */
-	0x60e0, /* 011000001110 */
-	0xf070, /* 111100000111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0x00, /* 111111110000 */
+	0x61, 0x80, /* 011000011000 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0x80, /* 011000001000 */
+	0x7f, 0x00, /* 011111110000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x6e, 0x00, /* 011011100000 */
+	0x67, 0x00, /* 011001110000 */
+	0x63, 0x80, /* 011000111000 */
+	0x61, 0xc0, /* 011000011100 */
+	0x60, 0xe0, /* 011000001110 */
+	0xf0, 0x70, /* 111100000111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 83 0x53 'S' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1fe0, /* 000111111110 */
-	0x3060, /* 001100000110 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x7000, /* 011100000000 */
-	0x3c00, /* 001111000000 */
-	0x1e00, /* 000111100000 */
-	0x0780, /* 000001111000 */
-	0x01c0, /* 000000011100 */
-	0x00e0, /* 000000001110 */
-	0x4060, /* 010000000110 */
-	0x4060, /* 010000000110 */
-	0x60c0, /* 011000001100 */
-	0x7f80, /* 011111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x30, 0x60, /* 001100000110 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x70, 0x00, /* 011100000000 */
+	0x3c, 0x00, /* 001111000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x07, 0x80, /* 000001111000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x00, 0xe0, /* 000000001110 */
+	0x40, 0x60, /* 010000000110 */
+	0x40, 0x60, /* 010000000110 */
+	0x60, 0xc0, /* 011000001100 */
+	0x7f, 0x80, /* 011111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 84 0x54 'T' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x4620, /* 010001100010 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x46, 0x20, /* 010001100010 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 85 0x55 'U' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf070, /* 111100000111 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x7040, /* 011100000100 */
-	0x3fc0, /* 001111111100 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0x70, /* 111100000111 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x70, 0x40, /* 011100000100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 86 0x56 'V' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xe0e0, /* 111000001110 */
-	0x6040, /* 011000000100 */
-	0x3080, /* 001100001000 */
-	0x3080, /* 001100001000 */
-	0x3080, /* 001100001000 */
-	0x1900, /* 000110010000 */
-	0x1900, /* 000110010000 */
-	0x1900, /* 000110010000 */
-	0x0a00, /* 000010100000 */
-	0x0e00, /* 000011100000 */
-	0x0e00, /* 000011100000 */
-	0x0400, /* 000001000000 */
-	0x0400, /* 000001000000 */
-	0x0400, /* 000001000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xe0, 0xe0, /* 111000001110 */
+	0x60, 0x40, /* 011000000100 */
+	0x30, 0x80, /* 001100001000 */
+	0x30, 0x80, /* 001100001000 */
+	0x30, 0x80, /* 001100001000 */
+	0x19, 0x00, /* 000110010000 */
+	0x19, 0x00, /* 000110010000 */
+	0x19, 0x00, /* 000110010000 */
+	0x0a, 0x00, /* 000010100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x04, 0x00, /* 000001000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 87 0x57 'W' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfef0, /* 111111101111 */
-	0x6620, /* 011001100010 */
-	0x6620, /* 011001100010 */
-	0x6620, /* 011001100010 */
-	0x7620, /* 011101100010 */
-	0x7740, /* 011101110100 */
-	0x3340, /* 001100110100 */
-	0x3740, /* 001101110100 */
-	0x3bc0, /* 001110111100 */
-	0x3b80, /* 001110111000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xfe, 0xf0, /* 111111101111 */
+	0x66, 0x20, /* 011001100010 */
+	0x66, 0x20, /* 011001100010 */
+	0x66, 0x20, /* 011001100010 */
+	0x76, 0x20, /* 011101100010 */
+	0x77, 0x40, /* 011101110100 */
+	0x33, 0x40, /* 001100110100 */
+	0x37, 0x40, /* 001101110100 */
+	0x3b, 0xc0, /* 001110111100 */
+	0x3b, 0x80, /* 001110111000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 88 0x58 'X' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf070, /* 111100000111 */
-	0x6020, /* 011000000010 */
-	0x3040, /* 001100000100 */
-	0x3880, /* 001110001000 */
-	0x1880, /* 000110001000 */
-	0x0d00, /* 000011010000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0b00, /* 000010110000 */
-	0x1180, /* 000100011000 */
-	0x11c0, /* 000100011100 */
-	0x20c0, /* 001000001100 */
-	0x4060, /* 010000000110 */
-	0xe0f0, /* 111000001111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0x70, /* 111100000111 */
+	0x60, 0x20, /* 011000000010 */
+	0x30, 0x40, /* 001100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x18, 0x80, /* 000110001000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x11, 0x80, /* 000100011000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x40, 0x60, /* 010000000110 */
+	0xe0, 0xf0, /* 111000001111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 89 0x59 'Y' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf070, /* 111100000111 */
-	0x6020, /* 011000000010 */
-	0x3040, /* 001100000100 */
-	0x1880, /* 000110001000 */
-	0x1880, /* 000110001000 */
-	0x0d00, /* 000011010000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0x70, /* 111100000111 */
+	0x60, 0x20, /* 011000000010 */
+	0x30, 0x40, /* 001100000100 */
+	0x18, 0x80, /* 000110001000 */
+	0x18, 0x80, /* 000110001000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 90 0x5a 'Z' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fe0, /* 001111111110 */
-	0x20c0, /* 001000001100 */
-	0x00c0, /* 000000001100 */
-	0x0180, /* 000000011000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x1820, /* 000110000010 */
-	0x3fe0, /* 001111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x20, 0xc0, /* 001000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x20, /* 000110000010 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 91 0x5b '[' */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x0f80, /* 000011111000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0f80, /* 000011111000 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 92 0x5c '\' */
-	0x0000, /* 000000000000 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0180, /* 000000011000 */
-	0x0180, /* 000000011000 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0060, /* 000000000110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x01, 0x80, /* 000000011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 93 0x5d ']' */
-	0x0000, /* 000000000000 */
-	0x1f00, /* 000111110000 */
-	0x1f00, /* 000111110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x1f00, /* 000111110000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 94 0x5e '^' */
-	0x0000, /* 000000000000 */
-	0x0400, /* 000001000000 */
-	0x0e00, /* 000011100000 */
-	0x1b00, /* 000110110000 */
-	0x3180, /* 001100011000 */
-	0x60c0, /* 011000001100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1b, 0x00, /* 000110110000 */
+	0x31, 0x80, /* 001100011000 */
+	0x60, 0xc0, /* 011000001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 95 0x5f '_' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 96 0x60 '`' */
-	0x0000, /* 000000000000 */
-	0x0100, /* 000000010000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0780, /* 000001111000 */
-	0x0780, /* 000001111000 */
-	0x0300, /* 000000110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x00, /* 000000010000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0x80, /* 000001111000 */
+	0x07, 0x80, /* 000001111000 */
+	0x03, 0x00, /* 000000110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 97 0x61 'a' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x10c0, /* 000100001100 */
-	0x03c0, /* 000000111100 */
-	0x1cc0, /* 000111001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1ee0, /* 000111101110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x10, 0xc0, /* 000100001100 */
+	0x03, 0xc0, /* 000000111100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0xe0, /* 000111101110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 98 0x62 'b' */
-	0x0000, /* 000000000000 */
-	0x2000, /* 001000000000 */
-	0x6000, /* 011000000000 */
-	0xe000, /* 111000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6780, /* 011001111000 */
-	0x6fc0, /* 011011111100 */
-	0x70e0, /* 011100001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7060, /* 011100000110 */
-	0x78c0, /* 011110001100 */
-	0x4f80, /* 010011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x20, 0x00, /* 001000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0xe0, 0x00, /* 111000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x67, 0x80, /* 011001111000 */
+	0x6f, 0xc0, /* 011011111100 */
+	0x70, 0xe0, /* 011100001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x60, /* 011100000110 */
+	0x78, 0xc0, /* 011110001100 */
+	0x4f, 0x80, /* 010011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 99 0x63 'c' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f80, /* 000111111000 */
-	0x31c0, /* 001100011100 */
-	0x20c0, /* 001000001100 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x7040, /* 011100000100 */
-	0x30c0, /* 001100001100 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x31, 0xc0, /* 001100011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x70, 0x40, /* 011100000100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 100 0x64 'd' */
-	0x0000, /* 000000000000 */
-	0x0060, /* 000000000110 */
-	0x00e0, /* 000000001110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x0f60, /* 000011110110 */
-	0x31e0, /* 001100011110 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x70e0, /* 011100001110 */
-	0x3960, /* 001110010110 */
-	0x1e70, /* 000111100111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0xe0, /* 000000001110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x0f, 0x60, /* 000011110110 */
+	0x31, 0xe0, /* 001100011110 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0xe0, /* 011100001110 */
+	0x39, 0x60, /* 001110010110 */
+	0x1e, 0x70, /* 000111100111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 101 0x65 'e' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x30c0, /* 001100001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7fe0, /* 011111111110 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x1860, /* 000110000110 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x60, /* 000110000110 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 102 0x66 'f' */
-	0x0000, /* 000000000000 */
-	0x0380, /* 000000111000 */
-	0x04c0, /* 000001001100 */
-	0x04c0, /* 000001001100 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x3f80, /* 001111111000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x1e00, /* 000111100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0x80, /* 000000111000 */
+	0x04, 0xc0, /* 000001001100 */
+	0x04, 0xc0, /* 000001001100 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 103 0x67 'g' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f20, /* 000111110010 */
-	0x31e0, /* 001100011110 */
-	0x60c0, /* 011000001100 */
-	0x60c0, /* 011000001100 */
-	0x60c0, /* 011000001100 */
-	0x3180, /* 001100011000 */
-	0x3f00, /* 001111110000 */
-	0x6000, /* 011000000000 */
-	0x7fc0, /* 011111111100 */
-	0x3fe0, /* 001111111110 */
-	0x2060, /* 001000000110 */
-	0x4020, /* 010000000010 */
-	0x4020, /* 010000000010 */
-	0x7fc0, /* 011111111100 */
-	0x3f80, /* 001111111000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x20, /* 000111110010 */
+	0x31, 0xe0, /* 001100011110 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x60, 0xc0, /* 011000001100 */
+	0x31, 0x80, /* 001100011000 */
+	0x3f, 0x00, /* 001111110000 */
+	0x60, 0x00, /* 011000000000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0xe0, /* 001111111110 */
+	0x20, 0x60, /* 001000000110 */
+	0x40, 0x20, /* 010000000010 */
+	0x40, 0x20, /* 010000000010 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 104 0x68 'h' */
-	0x0000, /* 000000000000 */
-	0x1000, /* 000100000000 */
-	0x3000, /* 001100000000 */
-	0x7000, /* 011100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3780, /* 001101111000 */
-	0x39c0, /* 001110011100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x79e0, /* 011110011110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x37, 0x80, /* 001101111000 */
+	0x39, 0xc0, /* 001110011100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x79, 0xe0, /* 011110011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 105 0x69 'i' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 106 0x6a 'j' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x03c0, /* 000000111100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x20c0, /* 001000001100 */
-	0x30c0, /* 001100001100 */
-	0x3880, /* 001110001000 */
-	0x1f00, /* 000111110000 */
-	0x0e00, /* 000011100000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0xc0, /* 000000111100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 107 0x6b 'k' */
-	0x0000, /* 000000000000 */
-	0x6000, /* 011000000000 */
-	0xe000, /* 111000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x61c0, /* 011000011100 */
-	0x6300, /* 011000110000 */
-	0x6600, /* 011001100000 */
-	0x7c00, /* 011111000000 */
-	0x7800, /* 011110000000 */
-	0x7c00, /* 011111000000 */
-	0x6e00, /* 011011100000 */
-	0x6700, /* 011001110000 */
-	0x6380, /* 011000111000 */
-	0xf1e0, /* 111100011110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0xe0, 0x00, /* 111000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x61, 0xc0, /* 011000011100 */
+	0x63, 0x00, /* 011000110000 */
+	0x66, 0x00, /* 011001100000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x7c, 0x00, /* 011111000000 */
+	0x6e, 0x00, /* 011011100000 */
+	0x67, 0x00, /* 011001110000 */
+	0x63, 0x80, /* 011000111000 */
+	0xf1, 0xe0, /* 111100011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 108 0x6c 'l' */
-	0x0000, /* 000000000000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 109 0x6d 'm' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xddc0, /* 110111011100 */
-	0x6ee0, /* 011011101110 */
-	0x6660, /* 011001100110 */
-	0x6660, /* 011001100110 */
-	0x6660, /* 011001100110 */
-	0x6660, /* 011001100110 */
-	0x6660, /* 011001100110 */
-	0x6660, /* 011001100110 */
-	0x6660, /* 011001100110 */
-	0xef70, /* 111011110111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xdd, 0xc0, /* 110111011100 */
+	0x6e, 0xe0, /* 011011101110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0x66, 0x60, /* 011001100110 */
+	0xef, 0x70, /* 111011110111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 110 0x6e 'n' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x2780, /* 001001111000 */
-	0x79c0, /* 011110011100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x79e0, /* 011110011110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x27, 0x80, /* 001001111000 */
+	0x79, 0xc0, /* 011110011100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x79, 0xe0, /* 011110011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 111 0x6f 'o' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7040, /* 011100000100 */
-	0x3880, /* 001110001000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 112 0x70 'p' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xef80, /* 111011111000 */
-	0x71c0, /* 011100011100 */
-	0x60e0, /* 011000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6040, /* 011000000100 */
-	0x7080, /* 011100001000 */
-	0x7f00, /* 011111110000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0xf000, /* 111100000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xef, 0x80, /* 111011111000 */
+	0x71, 0xc0, /* 011100011100 */
+	0x60, 0xe0, /* 011000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x40, /* 011000000100 */
+	0x70, 0x80, /* 011100001000 */
+	0x7f, 0x00, /* 011111110000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0xf0, 0x00, /* 111100000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 113 0x71 'q' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f20, /* 000011110010 */
-	0x11e0, /* 000100011110 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7060, /* 011100000110 */
-	0x38e0, /* 001110001110 */
-	0x1fe0, /* 000111111110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x0060, /* 000000000110 */
-	0x00f0, /* 000000001111 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x20, /* 000011110010 */
+	0x11, 0xe0, /* 000100011110 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x60, /* 011100000110 */
+	0x38, 0xe0, /* 001110001110 */
+	0x1f, 0xe0, /* 000111111110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0x60, /* 000000000110 */
+	0x00, 0xf0, /* 000000001111 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 114 0x72 'r' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7380, /* 011100111000 */
-	0x34c0, /* 001101001100 */
-	0x38c0, /* 001110001100 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x7800, /* 011110000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x73, 0x80, /* 011100111000 */
+	0x34, 0xc0, /* 001101001100 */
+	0x38, 0xc0, /* 001110001100 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 115 0x73 's' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1fc0, /* 000111111100 */
-	0x30c0, /* 001100001100 */
-	0x3040, /* 001100000100 */
-	0x3800, /* 001110000000 */
-	0x1e00, /* 000111100000 */
-	0x0780, /* 000001111000 */
-	0x01c0, /* 000000011100 */
-	0x20c0, /* 001000001100 */
-	0x30c0, /* 001100001100 */
-	0x3f80, /* 001111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0xc0, /* 000111111100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0x40, /* 001100000100 */
+	0x38, 0x00, /* 001110000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x07, 0x80, /* 000001111000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x3f, 0x80, /* 001111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 116 0x74 't' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0400, /* 000001000000 */
-	0x0400, /* 000001000000 */
-	0x0c00, /* 000011000000 */
-	0x7fc0, /* 011111111100 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c00, /* 000011000000 */
-	0x0c20, /* 000011000010 */
-	0x0e40, /* 000011100100 */
-	0x0780, /* 000001111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x7f, 0xc0, /* 011111111100 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0c, 0x20, /* 000011000010 */
+	0x0e, 0x40, /* 000011100100 */
+	0x07, 0x80, /* 000001111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 117 0x75 'u' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x79e0, /* 011110011110 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1e60, /* 000111100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x79, 0xe0, /* 011110011110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 118 0x76 'v' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf070, /* 111100000111 */
-	0x6020, /* 011000000010 */
-	0x3040, /* 001100000100 */
-	0x3040, /* 001100000100 */
-	0x1880, /* 000110001000 */
-	0x1880, /* 000110001000 */
-	0x0d00, /* 000011010000 */
-	0x0d00, /* 000011010000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0x70, /* 111100000111 */
+	0x60, 0x20, /* 011000000010 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x18, 0x80, /* 000110001000 */
+	0x18, 0x80, /* 000110001000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 119 0x77 'w' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xff70, /* 111111110111 */
-	0x6620, /* 011001100010 */
-	0x6620, /* 011001100010 */
-	0x6620, /* 011001100010 */
-	0x3740, /* 001101110100 */
-	0x3b40, /* 001110110100 */
-	0x3b40, /* 001110110100 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0x70, /* 111111110111 */
+	0x66, 0x20, /* 011001100010 */
+	0x66, 0x20, /* 011001100010 */
+	0x66, 0x20, /* 011001100010 */
+	0x37, 0x40, /* 001101110100 */
+	0x3b, 0x40, /* 001110110100 */
+	0x3b, 0x40, /* 001110110100 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 120 0x78 'x' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf8f0, /* 111110001111 */
-	0x7040, /* 011100000100 */
-	0x3880, /* 001110001000 */
-	0x1d00, /* 000111010000 */
-	0x0e00, /* 000011100000 */
-	0x0700, /* 000001110000 */
-	0x0b80, /* 000010111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0xf1f0, /* 111100011111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf8, 0xf0, /* 111110001111 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1d, 0x00, /* 000111010000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0b, 0x80, /* 000010111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0xf1, 0xf0, /* 111100011111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 121 0x79 'y' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf0f0, /* 111100001111 */
-	0x6020, /* 011000000010 */
-	0x3040, /* 001100000100 */
-	0x3040, /* 001100000100 */
-	0x1880, /* 000110001000 */
-	0x1880, /* 000110001000 */
-	0x0d00, /* 000011010000 */
-	0x0d00, /* 000011010000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0400, /* 000001000000 */
-	0x0c00, /* 000011000000 */
-	0x0800, /* 000010000000 */
-	0x7800, /* 011110000000 */
-	0x7000, /* 011100000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0xf0, /* 111100001111 */
+	0x60, 0x20, /* 011000000010 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x18, 0x80, /* 000110001000 */
+	0x18, 0x80, /* 000110001000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x08, 0x00, /* 000010000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 122 0x7a 'z' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x60e0, /* 011000001110 */
-	0x41c0, /* 010000011100 */
-	0x0380, /* 000000111000 */
-	0x0700, /* 000001110000 */
-	0x0e00, /* 000011100000 */
-	0x1c00, /* 000111000000 */
-	0x3820, /* 001110000010 */
-	0x7060, /* 011100000110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0xe0, /* 011000001110 */
+	0x41, 0xc0, /* 010000011100 */
+	0x03, 0x80, /* 000000111000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x38, 0x20, /* 001110000010 */
+	0x70, 0x60, /* 011100000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 123 0x7b '{' */
-	0x0000, /* 000000000000 */
-	0x0380, /* 000000111000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x3800, /* 001110000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0380, /* 000000111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0x80, /* 000000111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x38, 0x00, /* 001110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x80, /* 000000111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 124 0x7c '|' */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 125 0x7d '}' */
-	0x0000, /* 000000000000 */
-	0x1c00, /* 000111000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x01c0, /* 000000011100 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1c00, /* 000111000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x01, 0xc0, /* 000000011100 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1c, 0x00, /* 000111000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 126 0x7e '~' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1c20, /* 000111000010 */
-	0x3e60, /* 001111100110 */
-	0x67c0, /* 011001111100 */
-	0x4380, /* 010000111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1c, 0x20, /* 000111000010 */
+	0x3e, 0x60, /* 001111100110 */
+	0x67, 0xc0, /* 011001111100 */
+	0x43, 0x80, /* 010000111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 127 0x7f '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 128 0x80 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0fc0, /* 000011111100 */
-	0x1060, /* 000100000110 */
-	0x2020, /* 001000000010 */
-	0x2000, /* 001000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x2000, /* 001000000000 */
-	0x3020, /* 001100000010 */
-	0x1840, /* 000110000100 */
-	0x0f80, /* 000011111000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0180, /* 000000011000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xc0, /* 000011111100 */
+	0x10, 0x60, /* 000100000110 */
+	0x20, 0x20, /* 001000000010 */
+	0x20, 0x00, /* 001000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x20, 0x00, /* 001000000000 */
+	0x30, 0x20, /* 001100000010 */
+	0x18, 0x40, /* 000110000100 */
+	0x0f, 0x80, /* 000011111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x01, 0x80, /* 000000011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 129 0x81 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x79e0, /* 011110011110 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1e60, /* 000111100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x79, 0xe0, /* 011110011110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 130 0x82 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x30c0, /* 001100001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7fe0, /* 011111111110 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x1860, /* 000110000110 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x60, /* 000110000110 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 131 0x83 '.' */
-	0x0000, /* 000000000000 */
-	0x0200, /* 000000100000 */
-	0x0700, /* 000001110000 */
-	0x0d80, /* 000011011000 */
-	0x18c0, /* 000110001100 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x10c0, /* 000100001100 */
-	0x03c0, /* 000000111100 */
-	0x1cc0, /* 000111001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1ee0, /* 000111101110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x10, 0xc0, /* 000100001100 */
+	0x03, 0xc0, /* 000000111100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0xe0, /* 000111101110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 132 0x84 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x10c0, /* 000100001100 */
-	0x03c0, /* 000000111100 */
-	0x1cc0, /* 000111001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1ee0, /* 000111101110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x10, 0xc0, /* 000100001100 */
+	0x03, 0xc0, /* 000000111100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0xe0, /* 000111101110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 133 0x85 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x10c0, /* 000100001100 */
-	0x03c0, /* 000000111100 */
-	0x1cc0, /* 000111001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1ee0, /* 000111101110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x10, 0xc0, /* 000100001100 */
+	0x03, 0xc0, /* 000000111100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0xe0, /* 000111101110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 134 0x86 '.' */
-	0x0000, /* 000000000000 */
-	0x0700, /* 000001110000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0700, /* 000001110000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x10c0, /* 000100001100 */
-	0x03c0, /* 000000111100 */
-	0x1cc0, /* 000111001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1ee0, /* 000111101110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x07, 0x00, /* 000001110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x10, 0xc0, /* 000100001100 */
+	0x03, 0xc0, /* 000000111100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0xe0, /* 000111101110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 135 0x87 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f80, /* 000111111000 */
-	0x31c0, /* 001100011100 */
-	0x20c0, /* 001000001100 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x7040, /* 011100000100 */
-	0x30c0, /* 001100001100 */
-	0x1f80, /* 000111111000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0180, /* 000000011000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x31, 0xc0, /* 001100011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x70, 0x40, /* 011100000100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x01, 0x80, /* 000000011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 136 0x88 '.' */
-	0x0000, /* 000000000000 */
-	0x0200, /* 000000100000 */
-	0x0700, /* 000001110000 */
-	0x0d80, /* 000011011000 */
-	0x18c0, /* 000110001100 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x30c0, /* 001100001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7fe0, /* 011111111110 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x1860, /* 000110000110 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x60, /* 000110000110 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 137 0x89 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x30c0, /* 001100001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7fe0, /* 011111111110 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x1860, /* 000110000110 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x60, /* 000110000110 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 138 0x8a '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x30c0, /* 001100001100 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7fe0, /* 011111111110 */
-	0x6000, /* 011000000000 */
-	0x6000, /* 011000000000 */
-	0x3000, /* 001100000000 */
-	0x1860, /* 000110000110 */
-	0x0f80, /* 000011111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x60, 0x00, /* 011000000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x18, 0x60, /* 000110000110 */
+	0x0f, 0x80, /* 000011111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 139 0x8b '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 140 0x8c '.' */
-	0x0000, /* 000000000000 */
-	0x0400, /* 000001000000 */
-	0x0e00, /* 000011100000 */
-	0x1b00, /* 000110110000 */
-	0x3180, /* 001100011000 */
-	0x0000, /* 000000000000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x1b, 0x00, /* 000110110000 */
+	0x31, 0x80, /* 001100011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 141 0x8d '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1800, /* 000110000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 142 0x8e '.' */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0400, /* 000001000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0b00, /* 000010110000 */
-	0x0b00, /* 000010110000 */
-	0x1980, /* 000110011000 */
-	0x1180, /* 000100011000 */
-	0x3fc0, /* 001111111100 */
-	0x20c0, /* 001000001100 */
-	0x6060, /* 011000000110 */
-	0x4060, /* 010000000110 */
-	0xe0f0, /* 111000001111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x04, 0x00, /* 000001000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x11, 0x80, /* 000100011000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x40, 0x60, /* 010000000110 */
+	0xe0, 0xf0, /* 111000001111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 143 0x8f '.' */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x1980, /* 000110011000 */
-	0x0f00, /* 000011110000 */
-	0x0400, /* 000001000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0b00, /* 000010110000 */
-	0x0b00, /* 000010110000 */
-	0x1980, /* 000110011000 */
-	0x1180, /* 000100011000 */
-	0x3fc0, /* 001111111100 */
-	0x20c0, /* 001000001100 */
-	0x6060, /* 011000000110 */
-	0x4060, /* 010000000110 */
-	0xe0f0, /* 111000001111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x04, 0x00, /* 000001000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x11, 0x80, /* 000100011000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x60, 0x60, /* 011000000110 */
+	0x40, 0x60, /* 010000000110 */
+	0xe0, 0xf0, /* 111000001111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 144 0x90 '.' */
-	0x0000, /* 000000000000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0800, /* 000010000000 */
-	0x7fe0, /* 011111111110 */
-	0x3020, /* 001100000010 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3080, /* 001100001000 */
-	0x3f80, /* 001111111000 */
-	0x3080, /* 001100001000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3020, /* 001100000010 */
-	0x3020, /* 001100000010 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x08, 0x00, /* 000010000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x30, 0x20, /* 001100000010 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x80, /* 001100001000 */
+	0x3f, 0x80, /* 001111111000 */
+	0x30, 0x80, /* 001100001000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x20, /* 001100000010 */
+	0x30, 0x20, /* 001100000010 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 145 0x91 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3de0, /* 001111011110 */
-	0x6630, /* 011001100011 */
-	0x4630, /* 010001100011 */
-	0x0630, /* 000001100011 */
-	0x3ff0, /* 001111111111 */
-	0x6600, /* 011001100000 */
-	0xc600, /* 110001100000 */
-	0xc600, /* 110001100000 */
-	0xe730, /* 111001110011 */
-	0x7de0, /* 011111011110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3d, 0xe0, /* 001111011110 */
+	0x66, 0x30, /* 011001100011 */
+	0x46, 0x30, /* 010001100011 */
+	0x06, 0x30, /* 000001100011 */
+	0x3f, 0xf0, /* 001111111111 */
+	0x66, 0x00, /* 011001100000 */
+	0xc6, 0x00, /* 110001100000 */
+	0xc6, 0x00, /* 110001100000 */
+	0xe7, 0x30, /* 111001110011 */
+	0x7d, 0xe0, /* 011111011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 146 0x92 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x03f0, /* 000000111111 */
-	0x0710, /* 000001110001 */
-	0x0710, /* 000001110001 */
-	0x0b00, /* 000010110000 */
-	0x0b00, /* 000010110000 */
-	0x0b20, /* 000010110010 */
-	0x13e0, /* 000100111110 */
-	0x1320, /* 000100110010 */
-	0x3f00, /* 001111110000 */
-	0x2300, /* 001000110000 */
-	0x2300, /* 001000110000 */
-	0x4310, /* 010000110001 */
-	0x4310, /* 010000110001 */
-	0xe7f0, /* 111001111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0xf0, /* 000000111111 */
+	0x07, 0x10, /* 000001110001 */
+	0x07, 0x10, /* 000001110001 */
+	0x0b, 0x00, /* 000010110000 */
+	0x0b, 0x00, /* 000010110000 */
+	0x0b, 0x20, /* 000010110010 */
+	0x13, 0xe0, /* 000100111110 */
+	0x13, 0x20, /* 000100110010 */
+	0x3f, 0x00, /* 001111110000 */
+	0x23, 0x00, /* 001000110000 */
+	0x23, 0x00, /* 001000110000 */
+	0x43, 0x10, /* 010000110001 */
+	0x43, 0x10, /* 010000110001 */
+	0xe7, 0xf0, /* 111001111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 147 0x93 '.' */
-	0x0000, /* 000000000000 */
-	0x0200, /* 000000100000 */
-	0x0700, /* 000001110000 */
-	0x0d80, /* 000011011000 */
-	0x18c0, /* 000110001100 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7040, /* 011100000100 */
-	0x3880, /* 001110001000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 148 0x94 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7040, /* 011100000100 */
-	0x3880, /* 001110001000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 149 0x95 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0300, /* 000000110000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7040, /* 011100000100 */
-	0x3880, /* 001110001000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x03, 0x00, /* 000000110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 150 0x96 '.' */
-	0x0000, /* 000000000000 */
-	0x0200, /* 000000100000 */
-	0x0700, /* 000001110000 */
-	0x0d80, /* 000011011000 */
-	0x18c0, /* 000110001100 */
-	0x0000, /* 000000000000 */
-	0x79e0, /* 011110011110 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1e60, /* 000111100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x02, 0x00, /* 000000100000 */
+	0x07, 0x00, /* 000001110000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x79, 0xe0, /* 011110011110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 151 0x97 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1800, /* 000110000000 */
-	0x0c00, /* 000011000000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x79e0, /* 011110011110 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1e60, /* 000111100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x79, 0xe0, /* 011110011110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 152 0x98 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xf0f0, /* 111100001111 */
-	0x6020, /* 011000000010 */
-	0x3040, /* 001100000100 */
-	0x3040, /* 001100000100 */
-	0x1880, /* 000110001000 */
-	0x1880, /* 000110001000 */
-	0x0d00, /* 000011010000 */
-	0x0d00, /* 000011010000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0400, /* 000001000000 */
-	0x0c00, /* 000011000000 */
-	0x0800, /* 000010000000 */
-	0x7800, /* 011110000000 */
-	0x7000, /* 011100000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xf0, 0xf0, /* 111100001111 */
+	0x60, 0x20, /* 011000000010 */
+	0x30, 0x40, /* 001100000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x18, 0x80, /* 000110001000 */
+	0x18, 0x80, /* 000110001000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x0d, 0x00, /* 000011010000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x04, 0x00, /* 000001000000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x08, 0x00, /* 000010000000 */
+	0x78, 0x00, /* 011110000000 */
+	0x70, 0x00, /* 011100000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 153 0x99 '.' */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20c0, /* 001000001100 */
-	0x2060, /* 001000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x2040, /* 001000000100 */
-	0x3040, /* 001100000100 */
-	0x1880, /* 000110001000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xc0, /* 001000001100 */
+	0x20, 0x60, /* 001000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x20, 0x40, /* 001000000100 */
+	0x30, 0x40, /* 001100000100 */
+	0x18, 0x80, /* 000110001000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 154 0x9a '.' */
-	0x0000, /* 000000000000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0xe030, /* 111000000011 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x6020, /* 011000000010 */
-	0x7040, /* 011100000100 */
-	0x3fc0, /* 001111111100 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0xe0, 0x30, /* 111000000011 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x60, 0x20, /* 011000000010 */
+	0x70, 0x40, /* 011100000100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 155 0x9b '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x36c0, /* 001101101100 */
-	0x26c0, /* 001001101100 */
-	0x6600, /* 011001100000 */
-	0x6600, /* 011001100000 */
-	0x6600, /* 011001100000 */
-	0x6600, /* 011001100000 */
-	0x7640, /* 011101100100 */
-	0x36c0, /* 001101101100 */
-	0x1f80, /* 000111111000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x36, 0xc0, /* 001101101100 */
+	0x26, 0xc0, /* 001001101100 */
+	0x66, 0x00, /* 011001100000 */
+	0x66, 0x00, /* 011001100000 */
+	0x66, 0x00, /* 011001100000 */
+	0x66, 0x00, /* 011001100000 */
+	0x76, 0x40, /* 011101100100 */
+	0x36, 0xc0, /* 001101101100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 156 0x9c '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x1cc0, /* 000111001100 */
-	0x18c0, /* 000110001100 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x7e00, /* 011111100000 */
-	0x7e00, /* 011111100000 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x1800, /* 000110000000 */
-	0x3e20, /* 001111100010 */
-	0x7fe0, /* 011111111110 */
-	0x61c0, /* 011000011100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x18, 0xc0, /* 000110001100 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x7e, 0x00, /* 011111100000 */
+	0x7e, 0x00, /* 011111100000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x3e, 0x20, /* 001111100010 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x61, 0xc0, /* 011000011100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 157 0x9d '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x30c0, /* 001100001100 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0f00, /* 000011110000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 158 0x9e '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 159 0x9f '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 160 0xa0 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x18c0, /* 000110001100 */
-	0x10c0, /* 000100001100 */
-	0x03c0, /* 000000111100 */
-	0x1cc0, /* 000111001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1ee0, /* 000111101110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x18, 0xc0, /* 000110001100 */
+	0x10, 0xc0, /* 000100001100 */
+	0x03, 0xc0, /* 000000111100 */
+	0x1c, 0xc0, /* 000111001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0xe0, /* 000111101110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 161 0xa1 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x1e00, /* 000111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x1f80, /* 000111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1e, 0x00, /* 000111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 162 0xa2 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0f80, /* 000011111000 */
-	0x11c0, /* 000100011100 */
-	0x20e0, /* 001000001110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x6060, /* 011000000110 */
-	0x7040, /* 011100000100 */
-	0x3880, /* 001110001000 */
-	0x1f00, /* 000111110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x80, /* 000011111000 */
+	0x11, 0xc0, /* 000100011100 */
+	0x20, 0xe0, /* 001000001110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x60, 0x60, /* 011000000110 */
+	0x70, 0x40, /* 011100000100 */
+	0x38, 0x80, /* 001110001000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 163 0xa3 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0180, /* 000000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x79e0, /* 011110011110 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x1e60, /* 000111100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x01, 0x80, /* 000000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x79, 0xe0, /* 011110011110 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1e, 0x60, /* 000111100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 164 0xa4 '.' */
-	0x0000, /* 000000000000 */
-	0x1c40, /* 000111000100 */
-	0x3fc0, /* 001111111100 */
-	0x2380, /* 001000111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x2780, /* 001001111000 */
-	0x79c0, /* 011110011100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x79e0, /* 011110011110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1c, 0x40, /* 000111000100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x23, 0x80, /* 001000111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x27, 0x80, /* 001001111000 */
+	0x79, 0xc0, /* 011110011100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x79, 0xe0, /* 011110011110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 165 0xa5 '.' */
-	0x0000, /* 000000000000 */
-	0x1c40, /* 000111000100 */
-	0x3fc0, /* 001111111100 */
-	0x2380, /* 001000111000 */
-	0xc070, /* 110000000111 */
-	0x6020, /* 011000000010 */
-	0x7020, /* 011100000010 */
-	0x7820, /* 011110000010 */
-	0x5c20, /* 010111000010 */
-	0x4e20, /* 010011100010 */
-	0x4720, /* 010001110010 */
-	0x43a0, /* 010000111010 */
-	0x41e0, /* 010000011110 */
-	0x40e0, /* 010000001110 */
-	0x4060, /* 010000000110 */
-	0xe030, /* 111000000011 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1c, 0x40, /* 000111000100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x23, 0x80, /* 001000111000 */
+	0xc0, 0x70, /* 110000000111 */
+	0x60, 0x20, /* 011000000010 */
+	0x70, 0x20, /* 011100000010 */
+	0x78, 0x20, /* 011110000010 */
+	0x5c, 0x20, /* 010111000010 */
+	0x4e, 0x20, /* 010011100010 */
+	0x47, 0x20, /* 010001110010 */
+	0x43, 0xa0, /* 010000111010 */
+	0x41, 0xe0, /* 010000011110 */
+	0x40, 0xe0, /* 010000001110 */
+	0x40, 0x60, /* 010000000110 */
+	0xe0, 0x30, /* 111000000011 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 166 0xa6 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1f00, /* 000111110000 */
-	0x3180, /* 001100011000 */
-	0x0180, /* 000000011000 */
-	0x0780, /* 000001111000 */
-	0x1980, /* 000110011000 */
-	0x3180, /* 001100011000 */
-	0x3180, /* 001100011000 */
-	0x3380, /* 001100111000 */
-	0x1dc0, /* 000111011100 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x1f, 0x00, /* 000111110000 */
+	0x31, 0x80, /* 001100011000 */
+	0x01, 0x80, /* 000000011000 */
+	0x07, 0x80, /* 000001111000 */
+	0x19, 0x80, /* 000110011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x31, 0x80, /* 001100011000 */
+	0x33, 0x80, /* 001100111000 */
+	0x1d, 0xc0, /* 000111011100 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 167 0xa7 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0700, /* 000001110000 */
-	0x1980, /* 000110011000 */
-	0x10c0, /* 000100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x3080, /* 001100001000 */
-	0x1980, /* 000110011000 */
-	0x0e00, /* 000011100000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0x00, /* 000001110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x10, 0xc0, /* 000100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0x80, /* 001100001000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0e, 0x00, /* 000011100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 168 0xa8 '.' */
-	0x0000, /* 000000000000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0300, /* 000000110000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1800, /* 000110000000 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x3040, /* 001100000100 */
-	0x39c0, /* 001110011100 */
-	0x1f80, /* 000111111000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x03, 0x00, /* 000000110000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x00, /* 000110000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x40, /* 001100000100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x1f, 0x80, /* 000111111000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 169 0xa9 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 170 0xaa '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x00c0, /* 000000001100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0xc0, /* 000000001100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 171 0xab '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1000, /* 000100000000 */
-	0x3000, /* 001100000000 */
-	0x1000, /* 000100000000 */
-	0x1040, /* 000100000100 */
-	0x1080, /* 000100001000 */
-	0x1100, /* 000100010000 */
-	0x3a00, /* 001110100000 */
-	0x05c0, /* 000001011100 */
-	0x0a20, /* 000010100010 */
-	0x1020, /* 000100000010 */
-	0x20c0, /* 001000001100 */
-	0x4100, /* 010000010000 */
-	0x0200, /* 000000100000 */
-	0x03e0, /* 000000111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x10, 0x40, /* 000100000100 */
+	0x10, 0x80, /* 000100001000 */
+	0x11, 0x00, /* 000100010000 */
+	0x3a, 0x00, /* 001110100000 */
+	0x05, 0xc0, /* 000001011100 */
+	0x0a, 0x20, /* 000010100010 */
+	0x10, 0x20, /* 000100000010 */
+	0x20, 0xc0, /* 001000001100 */
+	0x41, 0x00, /* 010000010000 */
+	0x02, 0x00, /* 000000100000 */
+	0x03, 0xe0, /* 000000111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 172 0xac '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x1000, /* 000100000000 */
-	0x3000, /* 001100000000 */
-	0x1000, /* 000100000000 */
-	0x1040, /* 000100000100 */
-	0x1080, /* 000100001000 */
-	0x1100, /* 000100010000 */
-	0x3a40, /* 001110100100 */
-	0x04c0, /* 000001001100 */
-	0x0940, /* 000010010100 */
-	0x1240, /* 000100100100 */
-	0x2440, /* 001001000100 */
-	0x47e0, /* 010001111110 */
-	0x0040, /* 000000000100 */
-	0x0040, /* 000000000100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x10, 0x00, /* 000100000000 */
+	0x10, 0x40, /* 000100000100 */
+	0x10, 0x80, /* 000100001000 */
+	0x11, 0x00, /* 000100010000 */
+	0x3a, 0x40, /* 001110100100 */
+	0x04, 0xc0, /* 000001001100 */
+	0x09, 0x40, /* 000010010100 */
+	0x12, 0x40, /* 000100100100 */
+	0x24, 0x40, /* 001001000100 */
+	0x47, 0xe0, /* 010001111110 */
+	0x00, 0x40, /* 000000000100 */
+	0x00, 0x40, /* 000000000100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 173 0xad '.' */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 174 0xae '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0660, /* 000001100110 */
-	0x0cc0, /* 000011001100 */
-	0x1980, /* 000110011000 */
-	0x3300, /* 001100110000 */
-	0x6600, /* 011001100000 */
-	0x3300, /* 001100110000 */
-	0x1980, /* 000110011000 */
-	0x0cc0, /* 000011001100 */
-	0x0660, /* 000001100110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x60, /* 000001100110 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x33, 0x00, /* 001100110000 */
+	0x66, 0x00, /* 011001100000 */
+	0x33, 0x00, /* 001100110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x06, 0x60, /* 000001100110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 175 0xaf '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x6600, /* 011001100000 */
-	0x3300, /* 001100110000 */
-	0x1980, /* 000110011000 */
-	0x0cc0, /* 000011001100 */
-	0x0660, /* 000001100110 */
-	0x0cc0, /* 000011001100 */
-	0x1980, /* 000110011000 */
-	0x3300, /* 001100110000 */
-	0x6600, /* 011001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x66, 0x00, /* 011001100000 */
+	0x33, 0x00, /* 001100110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x06, 0x60, /* 000001100110 */
+	0x0c, 0xc0, /* 000011001100 */
+	0x19, 0x80, /* 000110011000 */
+	0x33, 0x00, /* 001100110000 */
+	0x66, 0x00, /* 011001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 176 0xb0 '.' */
-	0x0c30, /* 000011000011 */
-	0x0820, /* 000010000010 */
-	0x6180, /* 011000011000 */
-	0x2080, /* 001000001000 */
-	0x0c30, /* 000011000011 */
-	0x0820, /* 000010000010 */
-	0x6180, /* 011000011000 */
-	0x2080, /* 001000001000 */
-	0x0c30, /* 000011000011 */
-	0x0820, /* 000010000010 */
-	0x6180, /* 011000011000 */
-	0x2080, /* 001000001000 */
-	0x0c30, /* 000011000011 */
-	0x0820, /* 000010000010 */
-	0x6180, /* 011000011000 */
-	0x2080, /* 001000001000 */
-	0x0c30, /* 000011000011 */
-	0x0820, /* 000010000010 */
-	0x6180, /* 011000011000 */
-	0x2080, /* 001000001000 */
-	0x0c30, /* 000011000011 */
-	0x0820, /* 000010000010 */
+	0x0c, 0x30, /* 000011000011 */
+	0x08, 0x20, /* 000010000010 */
+	0x61, 0x80, /* 011000011000 */
+	0x20, 0x80, /* 001000001000 */
+	0x0c, 0x30, /* 000011000011 */
+	0x08, 0x20, /* 000010000010 */
+	0x61, 0x80, /* 011000011000 */
+	0x20, 0x80, /* 001000001000 */
+	0x0c, 0x30, /* 000011000011 */
+	0x08, 0x20, /* 000010000010 */
+	0x61, 0x80, /* 011000011000 */
+	0x20, 0x80, /* 001000001000 */
+	0x0c, 0x30, /* 000011000011 */
+	0x08, 0x20, /* 000010000010 */
+	0x61, 0x80, /* 011000011000 */
+	0x20, 0x80, /* 001000001000 */
+	0x0c, 0x30, /* 000011000011 */
+	0x08, 0x20, /* 000010000010 */
+	0x61, 0x80, /* 011000011000 */
+	0x20, 0x80, /* 001000001000 */
+	0x0c, 0x30, /* 000011000011 */
+	0x08, 0x20, /* 000010000010 */
 
 	/* 177 0xb1 '.' */
-	0x7770, /* 011101110111 */
-	0x2220, /* 001000100010 */
-	0x8880, /* 100010001000 */
-	0xddd0, /* 110111011101 */
-	0x8880, /* 100010001000 */
-	0x2220, /* 001000100010 */
-	0x7770, /* 011101110111 */
-	0x2220, /* 001000100010 */
-	0x8880, /* 100010001000 */
-	0xddd0, /* 110111011101 */
-	0x8880, /* 100010001000 */
-	0x2220, /* 001000100010 */
-	0x7770, /* 011101110111 */
-	0x2220, /* 001000100010 */
-	0x8880, /* 100010001000 */
-	0xddd0, /* 110111011101 */
-	0x8880, /* 100010001000 */
-	0x2220, /* 001000100010 */
-	0x7770, /* 011101110111 */
-	0x2220, /* 001000100010 */
-	0x8880, /* 100010001000 */
-	0xddd0, /* 110111011101 */
+	0x77, 0x70, /* 011101110111 */
+	0x22, 0x20, /* 001000100010 */
+	0x88, 0x80, /* 100010001000 */
+	0xdd, 0xd0, /* 110111011101 */
+	0x88, 0x80, /* 100010001000 */
+	0x22, 0x20, /* 001000100010 */
+	0x77, 0x70, /* 011101110111 */
+	0x22, 0x20, /* 001000100010 */
+	0x88, 0x80, /* 100010001000 */
+	0xdd, 0xd0, /* 110111011101 */
+	0x88, 0x80, /* 100010001000 */
+	0x22, 0x20, /* 001000100010 */
+	0x77, 0x70, /* 011101110111 */
+	0x22, 0x20, /* 001000100010 */
+	0x88, 0x80, /* 100010001000 */
+	0xdd, 0xd0, /* 110111011101 */
+	0x88, 0x80, /* 100010001000 */
+	0x22, 0x20, /* 001000100010 */
+	0x77, 0x70, /* 011101110111 */
+	0x22, 0x20, /* 001000100010 */
+	0x88, 0x80, /* 100010001000 */
+	0xdd, 0xd0, /* 110111011101 */
 
 	/* 178 0xb2 '.' */
-	0xf3c0, /* 111100111100 */
-	0xf7d0, /* 111101111101 */
-	0x9e70, /* 100111100111 */
-	0xdf70, /* 110111110111 */
-	0xf3c0, /* 111100111100 */
-	0xf7d0, /* 111101111101 */
-	0x9e70, /* 100111100111 */
-	0xdf70, /* 110111110111 */
-	0xf3c0, /* 111100111100 */
-	0xf7d0, /* 111101111101 */
-	0x9e70, /* 100111100111 */
-	0xdf70, /* 110111110111 */
-	0xf3c0, /* 111100111100 */
-	0xf7d0, /* 111101111101 */
-	0x9e70, /* 100111100111 */
-	0xdf70, /* 110111110111 */
-	0xf3c0, /* 111100111100 */
-	0xf7d0, /* 111101111101 */
-	0x9e70, /* 100111100111 */
-	0xdf70, /* 110111110111 */
-	0xf3c0, /* 111100111100 */
-	0xf7d0, /* 111101111101 */
+	0xf3, 0xc0, /* 111100111100 */
+	0xf7, 0xd0, /* 111101111101 */
+	0x9e, 0x70, /* 100111100111 */
+	0xdf, 0x70, /* 110111110111 */
+	0xf3, 0xc0, /* 111100111100 */
+	0xf7, 0xd0, /* 111101111101 */
+	0x9e, 0x70, /* 100111100111 */
+	0xdf, 0x70, /* 110111110111 */
+	0xf3, 0xc0, /* 111100111100 */
+	0xf7, 0xd0, /* 111101111101 */
+	0x9e, 0x70, /* 100111100111 */
+	0xdf, 0x70, /* 110111110111 */
+	0xf3, 0xc0, /* 111100111100 */
+	0xf7, 0xd0, /* 111101111101 */
+	0x9e, 0x70, /* 100111100111 */
+	0xdf, 0x70, /* 110111110111 */
+	0xf3, 0xc0, /* 111100111100 */
+	0xf7, 0xd0, /* 111101111101 */
+	0x9e, 0x70, /* 100111100111 */
+	0xdf, 0x70, /* 110111110111 */
+	0xf3, 0xc0, /* 111100111100 */
+	0xf7, 0xd0, /* 111101111101 */
 
 	/* 179 0xb3 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 180 0xb4 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 181 0xb5 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 182 0xb6 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfd80, /* 111111011000 */
-	0xfd80, /* 111111011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 183 0xb7 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xff80, /* 111111111000 */
-	0xff80, /* 111111111000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0x80, /* 111111111000 */
+	0xff, 0x80, /* 111111111000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 184 0xb8 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 185 0xb9 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfd80, /* 111111011000 */
-	0xfd80, /* 111111011000 */
-	0x0180, /* 000000011000 */
-	0xfd80, /* 111111011000 */
-	0xfd80, /* 111111011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0x01, 0x80, /* 000000011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 186 0xba '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 187 0xbb '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xff80, /* 111111111000 */
-	0xff80, /* 111111111000 */
-	0x0180, /* 000000011000 */
-	0xfd80, /* 111111011000 */
-	0xfd80, /* 111111011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0x80, /* 111111111000 */
+	0xff, 0x80, /* 111111111000 */
+	0x01, 0x80, /* 000000011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 188 0xbc '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfd80, /* 111111011000 */
-	0xfd80, /* 111111011000 */
-	0x0180, /* 000000011000 */
-	0xff80, /* 111111111000 */
-	0xff80, /* 111111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0xfd, 0x80, /* 111111011000 */
+	0x01, 0x80, /* 000000011000 */
+	0xff, 0x80, /* 111111111000 */
+	0xff, 0x80, /* 111111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 189 0xbd '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xff80, /* 111111111000 */
-	0xff80, /* 111111111000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xff, 0x80, /* 111111111000 */
+	0xff, 0x80, /* 111111111000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 190 0xbe '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 191 0xbf '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 192 0xc0 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 193 0xc1 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 194 0xc2 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 195 0xc3 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 196 0xc4 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 197 0xc5 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 198 0xc6 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 199 0xc7 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0df0, /* 000011011111 */
-	0x0df0, /* 000011011111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 200 0xc8 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0df0, /* 000011011111 */
-	0x0df0, /* 000011011111 */
-	0x0c00, /* 000011000000 */
-	0x0ff0, /* 000011111111 */
-	0x0ff0, /* 000011111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 201 0xc9 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0ff0, /* 000011111111 */
-	0x0ff0, /* 000011111111 */
-	0x0c00, /* 000011000000 */
-	0x0df0, /* 000011011111 */
-	0x0df0, /* 000011011111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 202 0xca '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfdf0, /* 111111011111 */
-	0xfdf0, /* 111111011111 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xfd, 0xf0, /* 111111011111 */
+	0xfd, 0xf0, /* 111111011111 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 203 0xcb '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0xfdf0, /* 111111011111 */
-	0xfdf0, /* 111111011111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0xfd, 0xf0, /* 111111011111 */
+	0xfd, 0xf0, /* 111111011111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 204 0xcc '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0df0, /* 000011011111 */
-	0x0df0, /* 000011011111 */
-	0x0c00, /* 000011000000 */
-	0x0df0, /* 000011011111 */
-	0x0df0, /* 000011011111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0c, 0x00, /* 000011000000 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0xf0, /* 000011011111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 205 0xcd '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 206 0xce '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfdf0, /* 111111011111 */
-	0xfdf0, /* 111111011111 */
-	0x0000, /* 000000000000 */
-	0xfdf0, /* 111111011111 */
-	0xfdf0, /* 111111011111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xfd, 0xf0, /* 111111011111 */
+	0xfd, 0xf0, /* 111111011111 */
+	0x00, 0x00, /* 000000000000 */
+	0xfd, 0xf0, /* 111111011111 */
+	0xfd, 0xf0, /* 111111011111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 207 0xcf '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 208 0xd0 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 209 0xd1 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 210 0xd2 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 211 0xd3 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0ff0, /* 000011111111 */
-	0x0ff0, /* 000011111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 212 0xd4 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 213 0xd5 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 214 0xd6 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0ff0, /* 000011111111 */
-	0x0ff0, /* 000011111111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x0f, 0xf0, /* 000011111111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 215 0xd7 '.' */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
-	0x0d80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
+	0x0d, 0x80, /* 000011011000 */
 
 	/* 216 0xd8 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0600, /* 000001100000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x06, 0x00, /* 000001100000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 217 0xd9 '.' */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0xfe00, /* 111111100000 */
-	0xfe00, /* 111111100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0xfe, 0x00, /* 111111100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 218 0xda '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x07f0, /* 000001111111 */
-	0x07f0, /* 000001111111 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x07, 0xf0, /* 000001111111 */
+	0x07, 0xf0, /* 000001111111 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
 
 	/* 219 0xdb '.' */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
 
 	/* 220 0xdc '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
 
 	/* 221 0xdd '.' */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
-	0xfc00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
+	0xfc, 0x00, /* 111111000000 */
 
 	/* 222 0xde '.' */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
-	0x03f0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
+	0x03, 0xf0, /* 000000111111 */
 
 	/* 223 0xdf '.' */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0xfff0, /* 111111111111 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0xff, 0xf0, /* 111111111111 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 224 0xe0 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 225 0xe1 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x1980, /* 000110011000 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x3180, /* 001100011000 */
-	0x3780, /* 001101111000 */
-	0x3180, /* 001100011000 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x3180, /* 001100011000 */
-	0x7700, /* 011101110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x31, 0x80, /* 001100011000 */
+	0x37, 0x80, /* 001101111000 */
+	0x31, 0x80, /* 001100011000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x31, 0x80, /* 001100011000 */
+	0x77, 0x00, /* 011101110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 226 0xe2 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 227 0xe3 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 228 0xe4 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 229 0xe5 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 230 0xe6 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x30c0, /* 001100001100 */
-	0x39c0, /* 001110011100 */
-	0x36e0, /* 001101101110 */
-	0x3000, /* 001100000000 */
-	0x3000, /* 001100000000 */
-	0x6000, /* 011000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x30, 0xc0, /* 001100001100 */
+	0x39, 0xc0, /* 001110011100 */
+	0x36, 0xe0, /* 001101101110 */
+	0x30, 0x00, /* 001100000000 */
+	0x30, 0x00, /* 001100000000 */
+	0x60, 0x00, /* 011000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 231 0xe7 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 232 0xe8 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 233 0xe9 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 234 0xea '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 235 0xeb '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 236 0xec '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 237 0xed '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 238 0xee '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 239 0xef '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 240 0xf0 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 241 0xf1 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 242 0xf2 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 243 0xf3 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 244 0xf4 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 245 0xf5 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 246 0xf6 '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x7fe0, /* 011111111110 */
-	0x7fe0, /* 011111111110 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x7f, 0xe0, /* 011111111110 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 247 0xf7 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 248 0xf8 '.' */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x1980, /* 000110011000 */
-	0x0f00, /* 000011110000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x19, 0x80, /* 000110011000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 249 0xf9 '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 250 0xfa '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0600, /* 000001100000 */
-	0x0f00, /* 000011110000 */
-	0x0f00, /* 000011110000 */
-	0x0600, /* 000001100000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 251 0xfb '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 252 0xfc '.' */
 	/* FIXME */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 253 0xfd '.' */
-	0x0000, /* 000000000000 */
-	0x0f00, /* 000011110000 */
-	0x1f80, /* 000111111000 */
-	0x3180, /* 001100011000 */
-	0x2180, /* 001000011000 */
-	0x0300, /* 000000110000 */
-	0x0600, /* 000001100000 */
-	0x0c00, /* 000011000000 */
-	0x1840, /* 000110000100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x0f, 0x00, /* 000011110000 */
+	0x1f, 0x80, /* 000111111000 */
+	0x31, 0x80, /* 001100011000 */
+	0x21, 0x80, /* 001000011000 */
+	0x03, 0x00, /* 000000110000 */
+	0x06, 0x00, /* 000001100000 */
+	0x0c, 0x00, /* 000011000000 */
+	0x18, 0x40, /* 000110000100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 254 0xfe '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x3fc0, /* 001111111100 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x3f, 0xc0, /* 001111111100 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 	/* 255 0xff '.' */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
-	0x0000, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
+	0x00, 0x00, /* 000000000000 */
 
 };
 
diff -u --recursive --new-file v2.1.131/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- v2.1.131/linux/drivers/video/imsttfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/imsttfb.c	Mon Dec 21 14:48:04 1998
@@ -51,11 +51,6 @@
 #define eieio()		/* Enforce In-order Execution of I/O */
 #endif
 
-enum {
-	IBM = 0x00,
-	TVP = 0x01
-};
-
 /* TwinTurbo (Cosmo) registers */
 enum {
 	S1SA	=  0, /* 0x00 */
@@ -63,7 +58,8 @@
 	SP	=  2, /* 0x08 */
 	DSA	=  3, /* 0x0C */
 	CNT	=  4, /* 0x10 */
-	DP_OCTRL=  5, /* 0x14 */
+	DP_OCTL	=  5, /* 0x14 */
+	CLR	=  6, /* 0x18 */
 	BI	=  8, /* 0x20 */
 	MBC	=  9, /* 0x24 */
 	BLTCTL	= 10, /* 0x28 */
@@ -113,7 +109,7 @@
 #endif
 };
 
-/* IBM ramdac direct registers */
+/* IBM 624 RAMDAC Direct Registers */
 enum {
 	PADDRW	= 0x00,
 	PDATA	= 0x04,
@@ -125,7 +121,7 @@
 	PIDXCTL	= 0x1c
 };
 
-/* IBM ramdac indirect registers */
+/* IBM 624 RAMDAC Indirect Registers */
 enum {
 	CLKCTL		= 0x02,	/* (0x01) Miscellaneous Clock Control */
 	SYNCCTL		= 0x03,	/* (0x00) Sync Control */
@@ -255,7 +251,7 @@
 	 * used in the 2MB and 4MB cards, at least.
 	 */
 	{ BPP8,		0x00 },
-	{ BPP16,	0x00 },
+	{ BPP16,	0x01 },
 	{ BPP24,	0x00 },
 	{ BPP32,	0x00 },
 
@@ -265,7 +261,7 @@
 	{ SYSCLKM,	0x4f },
 	{ SYSCLKP,	0x00 },
 	{ SYSCLKC,	0x00 },
-	{ CURSCTL,	0x02 },
+	{ CURSCTL,	0x00 },
 	{ CURSACCTL,	0x01 },
 	{ CURSACATTR,	0xa8 },
 	{ CURS1R,	0xff },
@@ -287,24 +283,24 @@
 };
 
 static struct initvalues tvp_initregs[] __initdata = {
-	{ 0x6,	0x00 },
-	{ 0x7,	0xe4 },
-	{ 0xf,	0x06 },
-	{ 0x18,	0x80 },
-	{ 0x19,	0x4d },
-	{ 0x1a,	0x05 },
-	{ 0x1c,	0x00 },
-	{ 0x1d,	0x00 },
-	{ 0x1e,	0x08 },
-	{ 0x30,	0xff },
-	{ 0x31,	0xff },
-	{ 0x32,	0xff },
-	{ 0x33,	0xff },
-	{ 0x34,	0xff },
-	{ 0x35,	0xff },
-	{ 0x36,	0xff },
-	{ 0x37,	0xff },
-	{ 0x38,	0x00 },
+	{ TVPIRICC,	0x00 },
+	{ TVPIRBRC,	0xe4 },
+	{ TVPIRLAC,	0x06 },
+	{ TVPIRTCC,	0x80 },
+	{ TVPIRMXC,	0x4d },
+	{ TVPIRCLS,	0x05 },
+	{ TVPIRPPG,	0x00 },
+	{ TVPIRGEC,	0x00 },
+	{ TVPIRMIC,	0x08 },
+	{ TVPIRCKL,	0xff },
+	{ TVPIRCKH,	0xff },
+	{ TVPIRCRL,	0xff },
+	{ TVPIRCRH,	0xff },
+	{ TVPIRCGL,	0xff },
+	{ TVPIRCGH,	0xff },
+	{ TVPIRCBL,	0xff },
+	{ TVPIRCBH,	0xff },
+	{ TVPIRCKC,	0x00 },
 	{ TVPIRPLA,	0x00 },
 	{ TVPIRPPD,	0xc0 },
 	{ TVPIRPPD,	0xd5 },
@@ -358,13 +354,18 @@
 	} palette[256];
 	struct imstt_regvals init;
 	struct imstt_cursor cursor;
-	volatile __u8 *frame_buffer_phys, *frame_buffer;
-	volatile __u32 *dc_regs_phys, *dc_regs;
-	volatile __u8 *cmap_regs_phys, *cmap_regs;
+	__u8 *frame_buffer_phys, *frame_buffer;
+	__u32 *dc_regs_phys, *dc_regs;
+	__u8 *cmap_regs_phys, *cmap_regs;
 	__u32 total_vram;
 	__u32 ramdac;
 };
 
+enum {
+	IBM = 0,
+	TVP = 1
+};
+
 #define USE_NV_MODES		1
 #define INIT_BPP		8
 #define INIT_XRES		640
@@ -379,6 +380,9 @@
 #if defined(CONFIG_PPC)
 static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
 #endif
+#ifdef MODULE
+static struct fb_info_imstt *fb_info_imstt_p[FB_MAX] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
 
 static struct imstt_regvals tvp_reg_init_2 = {
 	512,
@@ -619,7 +623,12 @@
 			lckl_p = init->lckl_p[1];
 			break;
 		case 24:
-			/* ?!? */
+			tcc = 0x5e;
+			mxc = 0x5d;
+			lckl_n = 0xf1;
+			mlc = init->mlc[2];
+			lckl_p = init->lckl_p[2];
+			break;
 		case 32:
 			tcc = 0x46;
 			mxc = 0x5d;
@@ -666,7 +675,7 @@
 set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
 {
 	struct imstt_regvals *init = &p->init;
-	__u32 ctl, pitch, byteswap, scr, line_pitch = init->pitch * (bpp >> 3);
+	__u32 ctl, pitch, byteswap, scr;
 
 	if (p->ramdac == IBM)
 		set_imstt_regvals_ibm(p, bpp);
@@ -682,7 +691,6 @@
    *     ==========     =====   =====
    *        8bpp          0       0
    *       16bpp          0       1
-   *       24bpp          1       0
    *       32bpp          1       1
    */
 	switch (bpp) {
@@ -737,64 +745,97 @@
 	}
 
 	switch (p->total_vram) {
-		case 0x00200000:
+		case 0x200000:
 			scr = 0x059d | byteswap;
 			break;
-		case 0x00400000:
-		case 0x00800000:
-			pitch /= 2;
+		/* case 0x400000:
+		   case 0x800000: */
+		default:
+			pitch >>= 1;
 			scr = 0x150dd | byteswap;
 			break;
 	}
 
 	out_le32(&p->dc_regs[SCR], scr);
 	out_le32(&p->dc_regs[SPR], pitch);
-	out_le32(&p->dc_regs[SP], (line_pitch << 16) | line_pitch);
-	out_le32(&p->dc_regs[DP_OCTRL], line_pitch);
-
 	out_le32(&p->dc_regs[STGCTL], ctl);
 }
 
-static void
-set_16 (struct fb_info_imstt *p, __u8 x)
+static inline void
+set_offset (struct display *disp, struct fb_info_imstt *p)
+{
+	__u32 off = disp->var.yoffset * (disp->line_length >> 3)
+		    + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
+	out_le32(&p->dc_regs[SSR], off);
+}
+
+static inline void
+set_555 (struct fb_info_imstt *p)
 {
 	if (p->ramdac == IBM) {
 		p->cmap_regs[PIDXHI] = 0;	eieio();
 		p->cmap_regs[PIDXLO] = BPP16;	eieio();
-		p->cmap_regs[PIDXDATA] = x;	eieio();
+		p->cmap_regs[PIDXDATA] = 0x01;	eieio();
 	} else {
-		/* ?!? */
+		p->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
+		p->cmap_regs[TVPIDATA] = 0x44;		eieio();
 	}
 }
 
-#define set_555(_p)	set_16(_p, 0x01)
-#define set_565(_p)	set_16(_p, 0x03)
+static inline void
+set_565 (struct fb_info_imstt *p)
+{
+	if (p->ramdac == IBM) {
+		p->cmap_regs[PIDXHI] = 0;	eieio();
+		p->cmap_regs[PIDXLO] = BPP16;	eieio();
+		p->cmap_regs[PIDXDATA] = 0x03;	eieio();
+	} else {
+		p->cmap_regs[TVPADDRW] = TVPIRTCC;	eieio();
+		p->cmap_regs[TVPIDATA] = 0x45;		eieio();
+	}
+}
 
 static void
 imstt_set_cursor (struct fb_info_imstt *p, int on)
 {
 	struct imstt_cursor *c = &p->cursor;
 
-	p->cmap_regs[PIDXHI] = 0;
-	if (!on) {
-		p->cmap_regs[PIDXLO] = CURSCTL;	eieio();
-		p->cmap_regs[PIDXDATA] = 0x00;	eieio();
+	if (p->ramdac == IBM) {
+		p->cmap_regs[PIDXHI] = 0;	eieio();
+		if (!on) {
+			p->cmap_regs[PIDXLO] = CURSCTL;	eieio();
+			p->cmap_regs[PIDXDATA] = 0x00;	eieio();
+		} else {
+			p->cmap_regs[PIDXLO] = CURSXHI;		eieio();
+			p->cmap_regs[PIDXDATA] = c->x >> 8;	eieio();
+			p->cmap_regs[PIDXLO] = CURSXLO;		eieio();
+			p->cmap_regs[PIDXDATA] = c->x & 0xff;	eieio();
+			p->cmap_regs[PIDXLO] = CURSYHI;		eieio();
+			p->cmap_regs[PIDXDATA] = c->y >> 8;	eieio();
+			p->cmap_regs[PIDXLO] = CURSYLO;		eieio();
+			p->cmap_regs[PIDXDATA] = c->y & 0xff;	eieio();
+			p->cmap_regs[PIDXLO] = CURSCTL;		eieio();
+			p->cmap_regs[PIDXDATA] = 0x02;		eieio();
+		}
 	} else {
-		p->cmap_regs[PIDXLO] = CURSXHI;		eieio();
-		p->cmap_regs[PIDXDATA] = c->x >> 8;	eieio();
-		p->cmap_regs[PIDXLO] = CURSXLO;		eieio();
-		p->cmap_regs[PIDXDATA] = c->x & 0xff;	eieio();
-		p->cmap_regs[PIDXLO] = CURSYHI;		eieio();
-		p->cmap_regs[PIDXDATA] = c->y >> 8;	eieio();
-		p->cmap_regs[PIDXLO] = CURSYLO;		eieio();
-		p->cmap_regs[PIDXDATA] = c->y & 0xff;	eieio();
-		p->cmap_regs[PIDXLO] = CURSCTL;		eieio();
-		p->cmap_regs[PIDXDATA] = 0x02;		eieio();
+		if (!on) {
+			p->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+			p->cmap_regs[TVPIDATA] = 0x00;		eieio();
+		} else {
+			__u16 x = c->x + 0x40, y = c->y + 0x40;
+
+			p->cmap_regs[TVPCXPOH] = x >> 8;	eieio();
+			p->cmap_regs[TVPCXPOL] = x & 0xff;	eieio();
+			p->cmap_regs[TVPCYPOH] = y >> 8;	eieio();
+			p->cmap_regs[TVPCYPOL] = y & 0xff;	eieio();
+			p->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+			p->cmap_regs[TVPIDATA] = 0x02;		eieio();
+		}
 	}
 }
 
 static void
-imsttfb_cursor (struct display *disp, int mode, int x, int y)
+imsttfbcon_cursor (struct display *disp, int mode, int x, int y)
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
 	struct imstt_cursor *c = &p->cursor;
@@ -827,11 +868,12 @@
 }
 
 static int
-imsttfb_set_font (struct display *disp, int width, int height)
+imsttfbcon_set_font (struct display *disp, int width, int height)
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
 	struct imstt_cursor *c = &p->cursor;
 	u_int x, y;
+	__u8 fgc;
 
 	if (width > 32 || height > 32)
 		return -EINVAL;
@@ -839,17 +881,68 @@
 	c->height = height;
 	c->width = width;
 
-	p->cmap_regs[PIDXHI] = 1;	eieio();
-	for (x = 0; x < 0x100; x++) {
-		p->cmap_regs[PIDXLO] = x;	eieio();
-		p->cmap_regs[PIDXDATA] = 0x00;	eieio();
-	}
-	p->cmap_regs[PIDXHI] = 1;	eieio();
-	for (y = 0; y < height; y++)
-		for (x = 0; x < width >> 2; x++) {
-			p->cmap_regs[PIDXLO] = x + y * 8;	eieio();
-			p->cmap_regs[PIDXDATA] = 0xff;		eieio();
+	fgc = ~attr_bgcol_ec(disp, disp->conp);
+
+	if (p->ramdac == IBM) {
+		p->cmap_regs[PIDXHI] = 1;	eieio();
+		for (x = 0; x < 0x100; x++) {
+			p->cmap_regs[PIDXLO] = x;	eieio();
+			p->cmap_regs[PIDXDATA] = 0x00;	eieio();
+		}
+		p->cmap_regs[PIDXHI] = 1;	eieio();
+		for (y = 0; y < height; y++)
+			for (x = 0; x < width >> 2; x++) {
+				p->cmap_regs[PIDXLO] = x + y * 8;	eieio();
+				p->cmap_regs[PIDXDATA] = 0xff;		eieio();
+			}
+		p->cmap_regs[PIDXHI] = 0;	eieio();
+		p->cmap_regs[PIDXLO] = CURS1R;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS1G;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS1B;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS2R;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS2G;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS2B;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS3R;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS3G;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+		p->cmap_regs[PIDXLO] = CURS3B;	eieio();
+		p->cmap_regs[PIDXDATA] = fgc;	eieio();
+	} else {
+		p->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+		p->cmap_regs[TVPIDATA] &= 0x03;		eieio();
+		p->cmap_regs[TVPADDRW] = 0;		eieio();
+		for (x = 0; x < 0x200; x++) {
+			p->cmap_regs[TVPCRDAT] = 0x00;	eieio();
 		}
+		for (x = 0; x < 0x200; x++) {
+			p->cmap_regs[TVPCRDAT] = 0xff;	eieio();
+		}
+		p->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+		p->cmap_regs[TVPIDATA] &= 0x03;		eieio();
+		for (y = 0; y < height; y++)
+			for (x = 0; x < width >> 3; x++) {
+				p->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
+				p->cmap_regs[TVPCRDAT] = 0xff;		eieio();
+			}
+		p->cmap_regs[TVPADDRW] = TVPIRICC;	eieio();
+		p->cmap_regs[TVPIDATA] |= 0x08;		eieio();
+		for (y = 0; y < height; y++)
+			for (x = 0; x < width >> 3; x++) {
+				p->cmap_regs[TVPADDRW] = x + y * 8;	eieio();
+				p->cmap_regs[TVPCRDAT] = 0xff;		eieio();
+			}
+		p->cmap_regs[TVPCADRW] = 0x00;	eieio();
+		for (x = 0; x < 12; x++) {
+			p->cmap_regs[TVPCDATA] = fgc;	eieio();
+		}
+	}
 
 	return 1;
 }
@@ -879,7 +972,7 @@
 {
 	struct imstt_cursor *c = &p->cursor;
 
-	imsttfb_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
+	imsttfbcon_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
 
 	c->enable = 1;
 	c->on = 1;
@@ -898,75 +991,152 @@
 }
 
 static void
-imsttfb_rectcopy (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
-	__u32	Bpp = disp->var.bits_per_pixel >> 3,
-		line_pitch = disp->line_length,
-		fb_offset_old, fb_offset_new;
+	__u32	Bpp, line_pitch,
+		fb_offset_old, fb_offset_new,
+		sp, dp_octl, cnt, bltctl;
 
-	fb_offset_old = sy * line_pitch + sx * Bpp;
-	fb_offset_new = dy * line_pitch + dx * Bpp;
+	Bpp = disp->var.bits_per_pixel >> 3,
 
-	while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
-	out_le32(&p->dc_regs[CNT], ((height - 1) << 16) | (width * Bpp - 1));
+	sy *= fontheight(disp);
+	sx *= fontwidth(disp);
+	sx *= Bpp;
+	dy *= fontheight(disp);
+	dx *= fontwidth(disp);
+	dx *= Bpp;
+	height *= fontheight(disp);
+	height--;
+	width *= fontwidth(disp);
+	width *= Bpp;
+	width--;
+
+	line_pitch = disp->line_length;
+	bltctl = 0x05;
+	sp = line_pitch << 16;
+	cnt = height << 16;
+
+	if (sy < dy) {
+		sy += height;
+		dy += height;
+		sp |= -(line_pitch) & 0xffff;
+		dp_octl = -(line_pitch) & 0xffff;
+	} else {
+		sp |= line_pitch;
+		dp_octl = line_pitch;
+	}
+	if (sx < dx) {
+		sx += width;
+		dx += width;
+		bltctl |= 0x80;
+		cnt |= -(width) & 0xffff;
+	} else {
+		cnt |= width;
+	}
+	fb_offset_old = sy * line_pitch + sx;
+	fb_offset_new = dy * line_pitch + dx;
+
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
 	out_le32(&p->dc_regs[S1SA], fb_offset_old);
-	/* out_le32(&p->dc_regs[S2SA], fb_offset_new); */
+	out_le32(&p->dc_regs[SP], sp);
 	out_le32(&p->dc_regs[DSA], fb_offset_new);
-	out_le32(&p->dc_regs[BLTCTL], 0xc0000005);
-	while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
-	while (in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+	out_le32(&p->dc_regs[CNT], cnt);
+	out_le32(&p->dc_regs[DP_OCTL], dp_octl);
+	out_le32(&p->dc_regs[BLTCTL], bltctl);
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
 }
 
 static void
-imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+imsttfbcon_clear (struct vc_data *conp, struct display *disp,
+		  int sy, int sx, int height, int width)
 {
-	/* XXX .. */
-	if (sy < dy || (sy == dy && sx < dx)) {
-		switch (disp->var.bits_per_pixel) {
-		case 8: fbcon_cfb8_bmove(disp, sy, sx, dy, dx, height, width); break;
-		case 16: fbcon_cfb16_bmove(disp, sy, sx, dy, dx, height, width); break;
-		case 24: fbcon_cfb24_bmove(disp, sy, sx, dy, dx, height, width); break;
-		case 32: fbcon_cfb32_bmove(disp, sy, sx, dy, dx, height, width); break;
-		}
-		return;
-	}
+	struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+	__u32 Bpp, line_pitch, bgc;
+
+	bgc = attr_bgcol_ec(disp, conp);
+	bgc |= (bgc << 8);
+	bgc |= (bgc << 16);
+
+	Bpp = disp->var.bits_per_pixel >> 3,
+	line_pitch = disp->line_length;
 
 	sy *= fontheight(disp);
+	sy *= line_pitch;
 	sx *= fontwidth(disp);
-	dy *= fontheight(disp);
-	dx *= fontwidth(disp);
+	sx *= Bpp;
 	height *= fontheight(disp);
+	height--;
 	width *= fontwidth(disp);
+	width *= Bpp;
+	width--;
+
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+	out_le32(&p->dc_regs[DSA], sy + sx);
+	out_le32(&p->dc_regs[CNT], (height << 16) | width);
+	out_le32(&p->dc_regs[DP_OCTL], line_pitch);
+	out_le32(&p->dc_regs[BI], 0xffffffff);
+	out_le32(&p->dc_regs[MBC], 0xffffffff);
+	out_le32(&p->dc_regs[CLR], bgc);
+	out_le32(&p->dc_regs[BLTCTL], 0x200000);
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+}
+
+static void
+imsttfbcon_revc (struct display *disp, int sx, int sy)
+{
+	struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+	__u32 Bpp, line_pitch, height, width;
+
+	Bpp = disp->var.bits_per_pixel >> 3,
+	line_pitch = disp->line_length;
 
-	imsttfb_rectcopy(disp, sy, sx, dy, dx, height, width);
+	height = fontheight(disp);
+	width = fontwidth(disp) * Bpp;
+	sy *= height;
+	sy *= line_pitch;
+	sx *= width;
+	height--;
+	width--;
+
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+	out_le32(&p->dc_regs[DSA], sy + sx);
+	out_le32(&p->dc_regs[S1SA], sy + sx);
+	out_le32(&p->dc_regs[CNT], (height << 16) | width);
+	out_le32(&p->dc_regs[DP_OCTL], line_pitch);
+	out_le32(&p->dc_regs[SP], line_pitch);
+	out_le32(&p->dc_regs[BLTCTL], 0x40005);
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+	while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
 }
 
 #ifdef FBCON_HAS_CFB8
 static struct display_switch fbcon_imstt8 = {
-	fbcon_cfb8_setup, imsttfbcon_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
-	fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+	fbcon_cfb8_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb8_putc,
+	fbcon_cfb8_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb8_clear_margins,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB16
 static struct display_switch fbcon_imstt16 = {
-	fbcon_cfb16_setup, imsttfbcon_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
-	fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+	fbcon_cfb16_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb16_putc,
+	fbcon_cfb16_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb16_clear_margins,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB24
 static struct display_switch fbcon_imstt24 = {
-	fbcon_cfb24_setup, imsttfbcon_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
-	fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+	fbcon_cfb24_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb24_putc,
+	fbcon_cfb24_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb24_clear_margins,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
 #ifdef FBCON_HAS_CFB32
 static struct display_switch fbcon_imstt32 = {
-	fbcon_cfb32_setup, imsttfbcon_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
-	fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+	fbcon_cfb32_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb32_putc,
+	fbcon_cfb32_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb32_clear_margins,
 	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
 };
 #endif
@@ -1049,11 +1219,12 @@
 	p->palette[regno].blue = blue;
 
 	/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
-	if (bpp == 16 && p->ramdac == TVP && fb_display[currcon].var.green.length == 5) {
-		p->cmap_regs[PADDRW] = regno << 3;	eieio();
-	} else {
-		p->cmap_regs[PADDRW] = regno;		eieio();
-	}
+	if (0 && bpp == 16)	/* screws up X */
+		p->cmap_regs[PADDRW] = regno << 3;
+	else
+		p->cmap_regs[PADDRW] = regno;
+	eieio();
+
 	p->cmap_regs[PDATA] = red;	eieio();
 	p->cmap_regs[PDATA] = green;	eieio();
 	p->cmap_regs[PDATA] = blue;	eieio();
@@ -1129,10 +1300,13 @@
 }
 
 static void
-set_disp (struct display *disp, struct fb_info_imstt *p)
+set_dispsw (struct display *disp, struct fb_info_imstt *p)
 {
 	u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
 
+	if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
+		disp->conp->vc_sw->con_cursor(disp->conp, CM_ERASE);
+
 	p->dispsw = fbcon_dummy;
 	disp->dispsw = &p->dispsw;
 	disp->dispsw_data = 0;
@@ -1150,7 +1324,7 @@
 			p->dispsw = accel ? fbcon_imstt8 : fbcon_cfb8;
 #endif
 			break;
-		case 16:	/* RGB 555 */
+		case 16:	/* RGB 555 or 565 */
 			if (disp->var.green.length != 6)
 				disp->var.red.offset = 10;
 			disp->var.red.length = 5;
@@ -1196,11 +1370,25 @@
 			break;
 	}
 
-	if (p->ramdac == IBM) {
-		p->dispsw.cursor = imsttfb_cursor;
-		p->dispsw.set_font = imsttfb_set_font;
+	if (accel && p->ramdac != IBM) {
+		p->dispsw.cursor = 0;
+		p->dispsw.set_font = 0;
 	}
 
+#ifdef CONFIG_FB_COMPAT_XPMAC
+	set_display_info(disp);
+#endif
+}
+
+static void
+set_disp (struct display *disp, struct fb_info_imstt *p)
+{
+	u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+	disp->fb_info = &p->info;
+
+	set_dispsw(disp, p);
+
 	disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
 					 	     : FB_VISUAL_DIRECTCOLOR;
 	disp->screen_base = (__u8 *)p->frame_buffer;
@@ -1222,8 +1410,6 @@
 		}
 	} else {
 		disp->scrollmode = SCROLL_YREDRAW;
-		disp->var.yoffset = disp->var.xoffset = 0;
-		out_le32(&p->dc_regs[SSR], 0);
 	}
 
 	disp->var.activate = 0;
@@ -1237,10 +1423,6 @@
 	disp->var.left_margin = disp->var.right_margin = 16;
 	disp->var.upper_margin = disp->var.lower_margin = 16;
 	disp->var.hsync_len = disp->var.vsync_len = 8;
-
-#ifdef CONFIG_FB_COMPAT_XPMAC
-	set_display_info(disp);
-#endif
 }
 
 static int
@@ -1248,7 +1430,7 @@
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
 	struct display *disp;
-	u_int oldbpp, oldxres, oldyres, oldgreenlen;
+	u_int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
 
 	disp = &fb_display[con];
 
@@ -1273,6 +1455,7 @@
 	oldxres = disp->var.xres;
 	oldyres = disp->var.yres;
 	oldgreenlen = disp->var.green.length;
+	oldaccel = disp->var.accel_flags;
 
 	disp->var.bits_per_pixel = var->bits_per_pixel;
 	disp->var.xres = var->xres;
@@ -1306,6 +1489,7 @@
 			return err;
 		do_install_cmap(con, info);
 	}
+	*var = disp->var;
 
 	return 0;
 }
@@ -1315,7 +1499,6 @@
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
 	struct display *disp = &fb_display[con];
-	__u32 off;
 
 	if (var->xoffset + disp->var.xres > disp->var.xres_virtual
 	    || var->yoffset + disp->var.yres > disp->var.yres_virtual)
@@ -1323,11 +1506,8 @@
 
 	disp->var.xoffset = var->xoffset;
 	disp->var.yoffset = var->yoffset;
-	if (con == currcon) {
-		off = var->yoffset * (disp->line_length >> 3)
-		      + ((var->xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
-		out_le32(&p->dc_regs[SSR], off);
-	}
+	if (con == currcon)
+		set_offset(disp, p);
 
 	return 0;
 }
@@ -1377,48 +1557,48 @@
 	       u_long arg, int con, struct fb_info *info)
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
-	__u8 init[2];
+	__u8 idx[2];
 	__u32 reg[2];
 
 	switch (cmd) {
 		case FBIMSTT_SETREG:
-			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			out_le32(&p->dc_regs[reg[0]], reg[1]);
 			return 0;
 		case FBIMSTT_GETREG:
-			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			reg[1] = in_le32(&p->dc_regs[reg[0]]);
 			if (copy_to_user((void *)(arg + 4), &reg[1], 4))
 				return -EFAULT;
 			return 0;
 		case FBIMSTT_SETCMAPREG:
-			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]);
 			return 0;
 		case FBIMSTT_GETCMAPREG:
-			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+			if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
 				return -EFAULT;
 			reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]);
 			if (copy_to_user((void *)(arg + 4), &reg[1], 4))
 				return -EFAULT;
 			return 0;
 		case FBIMSTT_SETIDXREG:
-			if (copy_from_user(init, (void *)arg, 2))
+			if (copy_from_user(idx, (void *)arg, 2))
 				return -EFAULT;
 			p->cmap_regs[PIDXHI] = 0;		eieio();
-			p->cmap_regs[PIDXLO] = init[0];		eieio();
-			p->cmap_regs[PIDXDATA] = init[1];	eieio();
+			p->cmap_regs[PIDXLO] = idx[0];		eieio();
+			p->cmap_regs[PIDXDATA] = idx[1];	eieio();
 			return 0;
 		case FBIMSTT_GETIDXREG:
-			if (copy_from_user(init, (void *)arg, 1))
+			if (copy_from_user(idx, (void *)arg, 1))
 				return -EFAULT;
 			p->cmap_regs[PIDXHI] = 0;		eieio();
-			p->cmap_regs[PIDXLO] = init[0];		eieio();
-			init[1] = p->cmap_regs[PIDXDATA];
-			if (copy_to_user((void *)(arg + 1), &init[1], 1))
+			p->cmap_regs[PIDXLO] = idx[0];		eieio();
+			idx[1] = p->cmap_regs[PIDXDATA];
+			if (copy_to_user((void *)(arg + 1), &idx[1], 1))
 				return -EFAULT;
 			return 0;
 		default:
@@ -1443,21 +1623,21 @@
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
 	struct display *old = &fb_display[currcon], *new = &fb_display[con];
-	__u32 off;
 
 	if (old->cmap.len)
 		fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
-	
-	if (p->ramdac == IBM)
-		imsttfb_cursor(old, CM_ERASE, p->cursor.x, p->cursor.y);
+
+	if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
+		old->conp->vc_sw->con_cursor(old->conp, CM_ERASE);
 
 	currcon = con;
 
 	if (old->var.xres != new->var.xres
 	    || old->var.yres != new->var.yres
 	    || old->var.bits_per_pixel != new->var.bits_per_pixel
-	    || old->var.green.length != new->var.green.length) {
-		set_disp(new, p);
+	    || old->var.green.length != new->var.green.length
+	    || old->var.accel_flags != new->var.accel_flags) {
+		set_dispsw(new, p);
 		if (!compute_imstt_regvals(p, new->var.xres, new->var.yres))
 			return -1;
 		if (new->var.bits_per_pixel == 16) {
@@ -1468,53 +1648,28 @@
 		}
 		set_imstt_regvals(p, new->var.bits_per_pixel);
 	}
-	if (old->var.yoffset != new->var.yoffset || old->var.xoffset != new->var.xoffset) {
-		off = new->var.yoffset * (new->line_length >> 3)
-		      + ((new->var.xoffset * (new->var.bits_per_pixel >> 3)) >> 3);
-		out_le32(&p->dc_regs[SSR], off);
-	}
+	set_offset(new, p);
+
+	imsttfbcon_set_font(new, fontwidth(new), fontheight(new));
 
 	do_install_cmap(con, info);
 
 	return 0;
 }
 
-static inline void
-imsttfb_rectfill (struct display *disp, u_int sy, u_int sx, u_int height, u_int width, __u32 bgx)
-{
-	memset(disp->screen_base + sy + sx, bgx, height * width * (disp->var.bits_per_pixel >> 3));
-}
-
 static int
 imsttfbcon_updatevar (int con, struct fb_info *info)
 {
 	struct fb_info_imstt *p = (struct fb_info_imstt *)info;
 	struct display *disp = &fb_display[con];
-	struct vc_data *conp = disp->conp;
-	__u32 off, yres, yoffset, sy, height;
 
 	if (con != currcon)
 		goto out;
 
-	yres = disp->var.yres;
-	yoffset = disp->var.yoffset;
-	sy = (conp->vc_rows + disp->yscroll) * fontheight(disp);
-	height = yres - conp->vc_rows * fontheight(disp);
-
-	if (height && (yoffset + yres > sy)) {
-		__u32 bgx = attr_bgcol_ec(disp, conp);
-
-		if (sy + height > disp->var.yres_virtual)
-			printk("updatevar: %u + %u > %u\n", sy, height, disp->var.yres_virtual);
-		imsttfb_rectfill(disp, sy, disp->var.xoffset, height, disp->var.xres, bgx);
-	}
-
-	if (p->ramdac == IBM && (yoffset + yres <= sy))
-		imsttfb_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
+	if (p->ramdac == IBM)
+		imsttfbcon_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
 
-	off = disp->var.yoffset * (disp->line_length >> 3)
-	      + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3); 
-	out_le32(&p->dc_regs[SSR], off);
+	set_offset(disp, p);
 
 out:
 	return 0;
@@ -1581,9 +1736,9 @@
 
 	tmp = in_le32(&p->dc_regs[PRC]);
 	if (p->ramdac == IBM)
-		p->total_vram = (tmp & 0x0004) ? 0x00400000 : 0x00200000;
+		p->total_vram = (tmp & 0x0004) ? 0x400000 : 0x200000;
 	else
-		p->total_vram = 0x00800000;
+		p->total_vram = 0x800000;
 
 	ip = (__u32 *)p->frame_buffer;
 	end = (__u32 *)(p->frame_buffer + p->total_vram);
@@ -1660,7 +1815,7 @@
 	p->disp.var.accel_flags = noaccel ? 0 : FB_ACCELF_TEXT;
 	set_disp(&p->disp, p);
 
-	if (p->ramdac == IBM)
+	if (!noaccel && p->ramdac == IBM)
 		imstt_cursor_init(p);
 	if (p->disp.var.green.length == 6)
 		set_565(p);
@@ -1693,64 +1848,65 @@
 		return;
 	}
 
+	i = GET_FB_IDX(p->info.node);
 	tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
-	printk("fb%d: %s frame buffer; %uMB vram; chip version %u\n",
-		GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20, tmp);
+	printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n",
+		i, p->fix.id, p->total_vram >> 20, tmp);
 
+#ifdef MODULE
+	fb_info_imstt_p[i] = p;
+#endif
 #ifdef CONFIG_FB_COMPAT_XPMAC
 	strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
 	display_info.fb_address = (__u32)p->frame_buffer_phys;
 	display_info.cmap_adr_address = (__u32)&p->cmap_regs_phys[PADDRW];
 	display_info.cmap_data_address = (__u32)&p->cmap_regs_phys[PDATA];
 	display_info.disp_reg_address = (__u32)p->dc_regs_phys;
-	set_display_info(&p->disp);
 	if (!console_fb_info)
 		console_fb_info = &p->info;
 #endif /* CONFIG_FB_COMPAT_XPMAC */
 }
 
-#if defined(CONFIG_FB_OF)
+#if defined(CONFIG_FB_OF) && !defined(MODULE)
 __initfunc(void
 imsttfb_of_init(struct device_node *dp))
 {
 	struct fb_info_imstt *p;
 	int i;
-	__u32 addr, size = 0;
+	__u32 addr = 0;
 	__u8 bus, devfn;
 	__u16 cmd;
 
 	for (i = 0; i < dp->n_addrs; i++) {
-		if (dp->addrs[i].size >= 0x02000000) {
+		if (dp->addrs[i].size >= 0x02000000)
 			addr = dp->addrs[i].address;
-			size = dp->addrs[i].size;
-		}
 	}
-	if (!size)
+	if (!addr)
 		return;
 
+	if (!pci_device_loc(dp, &bus, &devfn)) {
+		if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd) && !(cmd & PCI_COMMAND_MEMORY)) {
+			cmd |= PCI_COMMAND_MEMORY;
+			pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+		}
+	}
+
 	p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
 	if (!p)
 		return;
-
 	memset(p, 0, sizeof(struct fb_info_imstt));
-	p->frame_buffer_phys = (__u8 *)addr;
-	p->frame_buffer = (__u8 *)ioremap(addr, size);
-	p->dc_regs_phys = (__u32 *)(p->frame_buffer_phys + 0x00800000);
-	p->dc_regs = (__u32 *)(p->frame_buffer + 0x00800000);
-	p->cmap_regs_phys = (__u8 *)(p->frame_buffer_phys + 0x00840000);
-	p->cmap_regs = (__u8 *)(p->frame_buffer + 0x00840000);
 
-	if (dp->name[11] == '8')
+	if (dp->name[11] == '8' || (dp->name[6] == '3' && dp->name[7] == 'd'))
 		p->ramdac = TVP;
 	else
 		p->ramdac = IBM;
 
-	if (!pci_device_loc(dp, &bus, &devfn)) {
-		if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd)) {
-			cmd |= PCI_COMMAND_MEMORY;
-			pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
-		}
-	}
+	p->frame_buffer_phys = (__u8 *)addr;
+	p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
+	p->dc_regs_phys = (__u32 *)(addr + 0x800000);
+	p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
+	p->cmap_regs_phys = (__u8 *)(addr + 0x840000);
+	p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
 
 	init_imstt(p);
 }
@@ -1759,11 +1915,60 @@
 __initfunc(void
 imsttfb_init(void))
 {
-#if !defined(CONFIG_FB_OF)
-	/* ... */
-#endif
+#if defined(CONFIG_FB_OF) && !defined(MODULE)
+	/* We don't want to be called like this. */
+	/* We rely on Open Firmware (offb) instead. */
+#elif defined(CONFIG_PCI)
+	struct pci_dev *pdev;
+	struct fb_info_imstt *p;
+	__u32 addr;
+	__u16 cmd;
+
+	for (pdev = pci_devices; pdev; pdev = pdev->next) {
+		if (!(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+		      && (pdev->vendor == PCI_VENDOR_ID_IMS)))
+			continue;
+
+		pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+		if (!(cmd & PCI_COMMAND_MEMORY)) {
+			cmd |= PCI_COMMAND_MEMORY;
+			pci_write_config_word(pdev, PCI_COMMAND, cmd);
+		}
+
+		addr = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+		if (!addr)
+			continue;
+
+		p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
+		if (!p)
+			return;
+		memset(p, 0, sizeof(struct fb_info_imstt));
+
+		printk("imsttfb: device=%04x\n", pdev->device);
+
+		switch (pdev->device) {
+			case 0x9128:	/* IMS,tt128mbA */
+				p->ramdac = IBM;
+				break;
+			case 0x9135:	/* IMS,tt3d */
+			default:
+				p->ramdac = TVP;
+				break;
+		}
+
+		p->frame_buffer_phys = (__u8 *)addr;
+		p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
+		p->dc_regs_phys = (__u32 *)(addr + 0x800000);
+		p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
+		p->cmap_regs_phys = (__u8 *)(addr + 0x840000);
+		p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
+
+		init_imstt(p);
+	}
+#endif /* CONFIG_PCI */
 }
 
+#ifndef MODULE
 __initfunc(void
 imsttfb_setup(char *options, int *ints))
 {
@@ -1816,3 +2021,42 @@
 #endif
 	}
 }
+
+#else /* MODULE */
+
+int
+init_module (void)
+{
+	struct fb_info_imstt *p;
+	__u32 i;
+
+	imsttfb_init();
+
+	for (i = 0; i < FB_MAX; i++) {
+		p = fb_info_imstt_p[i];
+		if (p)
+			return 0;
+	}
+
+	return -ENXIO;
+}
+
+void
+cleanup_module (void)
+{
+	struct fb_info_imstt *p;
+	__u32 i;
+
+	for (i = 0; i < FB_MAX; i++) {
+		p = fb_info_imstt_p[i];
+		if (!p)
+			continue;
+		iounmap(p->cmap_regs);
+		iounmap(p->dc_regs);
+		iounmap(p->frame_buffer);
+		kfree(p);
+	}
+}
+
+#include "macmodes.c"
+#endif /* MODULE */
diff -u --recursive --new-file v2.1.131/linux/drivers/video/macfb.c linux/drivers/video/macfb.c
--- v2.1.131/linux/drivers/video/macfb.c	Mon Oct  5 13:13:42 1998
+++ linux/drivers/video/macfb.c	Mon Dec 21 14:48:04 1998
@@ -22,6 +22,7 @@
 #include <asm/macintosh.h>
 #include <linux/fb.h>
 
+#include <video/fbcon.h>
 /* conditionalize these ?? */
 #include <video/fbcon-mfb.h>
 #include <video/fbcon-cfb2.h>
@@ -154,13 +155,15 @@
 	strcpy(fix->id,"Macintosh");
 
 	/*
-	 * X works, but screen wraps ... 
+	 * fbmem.c accepts non page aligned mappings now!
 	 */
-	fix->smem_start=(char *)(mac_videobase&PAGE_MASK);
-	fix->smem_offset=(mac_videobase&~PAGE_MASK);
-	fix->smem_len=PAGE_ALIGN(mac_videosize);
+	fix->smem_start=(char *)mac_videobase;
+	fix->smem_len=mac_videosize;
 	fix->type = FB_TYPE_PACKED_PIXELS;
-	fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	if (mac_depth == 1)
+		fix->visual = FB_VISUAL_MONO01;
+	else
+		fix->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
 	fix->xpanstep=0;
 	fix->ypanstep=0;
 	fix->ywrapstep=0;
@@ -203,7 +206,7 @@
 
 	macfb_get_fix(&fix, con, 0);
 
-	display->screen_base = fix.smem_start+fix.smem_offset;
+	display->screen_base = fix.smem_start;
 	display->visual = fix.visual;
 	display->type = fix.type;
 	display->type_aux = fix.type_aux;
@@ -212,7 +215,8 @@
 	display->line_length = fix.line_length;
 	display->next_line = fix.line_length;
 	display->can_soft_blank = 0;
-	display->inverse = inverse;
+	display->inverse =
+	    (fix.visual == FB_VISUAL_MONO01 ? !inverse : inverse);
 
 	switch (mac_depth) {
 #ifdef FBCON_HAS_MFB
@@ -251,6 +255,140 @@
 	return 0;
 }
 
+/*
+ * Color map handling - hardcoded maps!! 
+ *
+ * 2.0 color map primitives, copied from atafb.c
+ */
+ 
+/*
+ * should be kmalloc'ed on request
+ */
+static short red256[256], green256[256], blue256[256];
+
+static short red16[]=
+	{ 0x0000,0x0000,0x0000,0x0000,0x8080,0x8080,0x8080,0xc0c0,
+	  0x8080,0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff};
+static short green16[]=
+	{ 0x0000,0x0000,0x8080,0x8080,0x0000,0x0000,0x8080,0xc0c0,
+	  0x8080,0x0000,0xffff,0xffff,0x0000,0x0000,0xffff,0xffff};
+static short blue16[]=
+	{ 0x0000,0x8080,0x0000,0x8080,0x0000,0x8080,0x0000,0xc0c0,
+	  0x8080,0xffff,0x0000,0xffff,0x0000,0xffff,0x0000,0xffff};
+
+static short red4[]=
+	{ 0x0000,0x8080,0xffff,0xffff};
+static short green4[]=
+	{ 0x0000,0x8080,0x0000,0xffff};
+static short blue4[]=
+	{ 0x0000,0x8080,0x0000,0xffff};
+
+static short red2[]=
+	{ 0x0000,0xffff};
+static short green2[]=
+	{ 0x0000,0xffff};
+static short blue2[]=
+	{ 0x0000,0xffff};
+
+struct fb_cmap default_256_colors = { 0, 256, red256, green256, blue256, NULL };
+struct fb_cmap default_16_colors  = { 0, 16, red16, green16, blue16, NULL };
+struct fb_cmap default_4_colors   = { 0, 4, red4, green4, blue4, NULL };
+struct fb_cmap default_2_colors   = { 0, 2, red2, green2, blue2, NULL };
+
+static int mac_set_cmap256(struct fb_cmap* cmap)
+{
+	int i,start;
+	unsigned short *red,*green,*blue;
+	unsigned short cval[] = {0xffff, 0xcccc, 0x9999, 
+				 0x6666, 0x3333, 0x0000 };
+	unsigned short gval[] = {0x0a0a, 0x1414, 0x1e1e,
+				 0x2828, 0x3232, 0x3c3c,
+				 0x4646, 0x5050, 0x5a5a,
+				 0x6464, 0x6e6e, 0x7878,
+				 0x8282, 0x8c8c, 0x9696,
+				 0xa0a0, 0xaaaa, 0xb4b4,
+				 0xbebe, 0xc8c8, 0xd2d2,
+				 0xdcdc, 0xe6e6, 0xf0f0};
+
+	red=cmap->red;
+	green=cmap->green;
+	blue=cmap->blue;
+	start=cmap->start;
+
+	if (start < 0)
+		return -EINVAL;
+	if (cmap->len < 255)
+		return -EINVAL;
+	/* 16 ANSI colors */
+	for (i=0 ; i < 16 ; i++) {
+		*red++   = red16[i];
+		*green++ = green16[i];
+		*blue++  = blue16[i];
+	}
+	/* 216 colors (6x6x6) map) */
+	for (i=16 ; i < 232 ; i++) {
+		*red++   = cval[(i-16)/36];
+		*green++ = cval[((i-16)/6)%6];
+		*blue++  = cval[(i-16)%6];
+	}
+	/* 24 grays */
+	for (i=232 ; i < 256 ; i++) {
+		*red = *green = *blue = gval[i-232];
+		red++;
+		green++;
+		blue++;
+	}
+	return 0;
+}
+
+static struct fb_cmap * mac_get_default_cmap(int bpp)
+{
+	if (bpp == 1)
+		return &default_2_colors;
+	if (bpp == 2)
+		return &default_4_colors;
+	if (bpp == 4)
+		return &default_16_colors;
+	return &default_256_colors;
+}
+
+static void memcpy_fs(int fsfromto, void *to, void *from, int len)
+{
+    switch (fsfromto) {
+    	case 0:
+    	    memcpy(to, from, len);
+    	    return;
+    	case 1:
+    	    copy_from_user(to, from, len);
+    	    return;
+    	case 2:
+    	    copy_to_user(to, from, len);
+    	    return;
+    }
+}
+
+static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
+{
+	int size;
+	int tooff=0, fromoff=0;
+
+	if (to->start > from->start)
+		fromoff=to->start-from->start;
+	else
+		tooff=from->start-to->start;			
+	size=to->len-tooff;
+	if (size > from->len-fromoff)
+		size=from->len-fromoff;
+	if (size < 0)
+		return;
+	size*=sizeof(unsigned short);
+	memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
+	memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
+	memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
+	if (from->transp && to->transp)
+		memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
+}
+ 
 static int macfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			  struct fb_info *info)
 {
@@ -267,6 +405,8 @@
 		fb_copy_cmap(fb_default_cmap(fb_display[con].var.bits_per_pixel),
 		     cmap, kspc ? 0 : 2);
 #endif
+	copy_cmap(mac_get_default_cmap(fb_display[con].var.bits_per_pixel),
+	     cmap, kspc ? 0 : 2);
 	return 0;
 
 }
@@ -387,11 +527,9 @@
 	mac_videosize=mac_xbytes*mac_yres;
 	mac_videobase=mac_bi_data.videoaddr;
 
-	printk("macfb_init: xres %d yres %d bpp %d addr %x size %d \n",
+	printk("macfb_init: xres %d yres %d bpp %d addr %lx size %ld \n",
 		mac_xres, mac_yres, mac_depth, mac_videobase, mac_videosize);
 
-	mac_debugging_penguin(4);
-	
 	/*
 	 *	Fill in the available video resolution
 	 */
@@ -421,6 +559,12 @@
 	macfb_set_disp(-1);
 
 	/*
+	 *	Fill in the 8 bit color table if required
+	 */
+	if (mac_depth == 8)
+		mac_set_cmap256(&default_256_colors);
+	 	
+	/*
 	 *	Register the nubus hook
 	 */
 	 
@@ -428,7 +572,6 @@
 
 	if (register_framebuffer(&fb_info) < 0)
 	{
-		mac_boom(6);
 		return;
 	}
 
diff -u --recursive --new-file v2.1.131/linux/drivers/video/matroxfb.c linux/drivers/video/matroxfb.c
--- v2.1.131/linux/drivers/video/matroxfb.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/matroxfb.c	Mon Dec 21 14:48:04 1998
@@ -4,7 +4,7 @@
  *
  * (c) 1998 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.5 1998/11/19 
+ * Version: 1.8 1998/12/11
  *
  * MTRR stuff: 1998 Tom Rini <tmrini@ntplx.net>
  *
@@ -21,10 +21,14 @@
  *                     Access device through readb|w|l and write b|w|l
  *                     Extensive debugging stuff
  *
+ *               "Daniel Haun" <haund@usa.net>
+ *                     Testing, hardware cursor fixes
+ *
  *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
  *                     Betatesting
  *
  *               "Kelly French" <targon@hazmat.com>
+ *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
  *                     Betatesting, bug reporting
  *
  *               "Pablo Bianucci" <pbian@pccp.com.ar>
@@ -39,7 +43,14 @@
  *               "Paul Womar" <Paul@pwomar.demon.co.uk>
  *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
  *                     PPC betatesting 
- *                     
+ *
+ *               "Thomas Pornin" <pornin@bolet.ens.fr>
+ *                     Alpha betatesting
+ *
+ *               "Pieter van Leuven" <pvl@iae.nl>
+ *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
+ *                     G100 testing
+ *
  *               "H. Peter Arvin" <hpa@transmeta.com>
  *                     Ideas
  *
@@ -100,15 +111,17 @@
 #include <video/fbcon-cfb24.h>
 #include <video/fbcon-cfb32.h>
 
+#if defined(CONFIG_PPC)
 #if defined(CONFIG_FB_COMPAT_XPMAC)
 #include <asm/vc_ioctl.h>
 #endif
-#if defined(CONFIG_PPC)
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <video/macmodes.h>
 #endif
 
+#define FBCON_HAS_VGATEXT
+
 #ifdef MATROXFB_DEBUG
 
 #define DEBUG
@@ -185,6 +198,9 @@
 #ifndef PCI_SS_VENDOR_ID_MATROX
 #define PCI_SS_VENDOR_ID_MATROX		PCI_VENDOR_ID_MATROX
 #endif
+#ifndef PCI_DEVICE_ID_MATROX_G200_PCI
+#define PCI_DEVICE_ID_MATROX_G200_PCI	0x0520
+#endif
 #ifndef PCI_DEVICE_ID_MATROX_G200_AGP
 #define PCI_DEVICE_ID_MATROX_G200_AGP	0x0521
 #endif
@@ -228,6 +244,10 @@
 	return readb(va.vaddr + offs);
 }
 
+static inline unsigned int mga_readw(vaddr_t va, unsigned int offs) {
+	return readw(va.vaddr + offs);
+}
+
 static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
 	return readl(va.vaddr + offs);
 }
@@ -248,6 +268,10 @@
 	return *(volatile u_int8_t*)(va.vaddr + offs);
 }
 
+static inline unsigned int mga_readw(vaddr_t va, unsigned int offs) {
+	return *(volatile u_int16_t*)(va.vaddr + offs);
+}
+
 static inline u_int32_t mga_readl(vaddr_t va, unsigned int offs) {
 	return *(volatile u_int32_t*)(va.vaddr + offs);
 }
@@ -334,12 +358,13 @@
 
 struct matroxfb_par
 {
-	struct fb_var_screeninfo var;
-
 	unsigned int	final_bppShift;
-	int		visual;		/* unfortunately, fix */
-	int		video_type;
 	unsigned int	cmap_len;
+	struct {
+		unsigned int bytes;
+		unsigned int pixels;
+		unsigned int chunks;
+		      } ydstorg;
 	void		(*putc)(u_int32_t, u_int32_t, struct display*, int, int, int);
 	void		(*putcs)(u_int32_t, u_int32_t, struct display*, const unsigned short*, int, int, int);
 };
@@ -407,8 +432,8 @@
 };
 
 #ifdef CONFIG_FB_MATROX_MULTIHEAD
-#define ACCESS_FBINFO(x) (minfo->x)
-#define ACCESS_FBINFO2(info, x) (((struct matrox_fb_info*)info)->x)
+#define ACCESS_FBINFO2(info, x) (info->x)
+#define ACCESS_FBINFO(x) ACCESS_FBINFO2(minfo,x)
 
 #define MINFO minfo
 
@@ -451,7 +476,7 @@
 struct matrox_switch {
 	int	(*preinit)(WPMINFO struct matrox_hw_state*);
 	void	(*reset)(WPMINFO struct matrox_hw_state*);
-	int	(*init)(CPMINFO struct matrox_hw_state*, struct my_timming*);
+	int	(*init)(CPMINFO struct matrox_hw_state*, struct my_timming*, struct display*);
 	void	(*restore)(WPMINFO struct matrox_hw_state*, struct matrox_hw_state*, struct display*);
 };
 
@@ -469,11 +494,6 @@
 
 	struct matrox_accel_data accel;
 
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-	unsigned int	_mga_ydstorg;
-	unsigned int	_curr_ydstorg;
-#endif
-
 	struct pci_dev*		pcidev;
 
 	struct {
@@ -511,6 +531,7 @@
 		int		cfb4;
 		const int*	vxres;
 		int		cross4MB;
+		int		text;
 			      } capable;
 	struct {
 		unsigned int	size;
@@ -529,12 +550,21 @@
 		int		novga;
 		int		nobios;
 		int		nopciretry;
+		int		noinit;
 		int		inverse;
 		int		hwcursor;
 		int		blink;
 
 		int		accelerator;
+		int		text_type_aux;
 		int		video64bits;
+		unsigned int	vgastep;
+		unsigned int	vgastepdisp;
+		unsigned int	textmode;
+		unsigned int	textstep;
+		unsigned int	textvram;	/* character cells */
+		unsigned int	ydstorg;	/* offset in bytes from video start to usable memory */
+						/* 0 except for 6MB Millenium */
 			      } devflags;
 	struct display_switch	dispsw;
 	struct {
@@ -545,6 +575,7 @@
 		unsigned int	d;
 		unsigned int	type;
 		int		state;
+		int		redraw;
 		struct timer_list timer;
 			      } cursor;
 #if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
@@ -561,27 +592,19 @@
 	} cmap;
 #endif
 	struct { unsigned red, green, blue, transp; } palette[256];
-#if defined(CONFIG_FB_COMPAT_XPMAC)
+#if defined(CONFIG_PPC) && defined(CONFIG_FB_COMPAT_XPMAC)
 	char	matrox_name[32];
 #endif
 };
 
 #if defined(CONFIG_PPC)
 unsigned char nvram_read_byte(int);
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
 #endif
 #if defined(CONFIG_FB_OF)
-void matrox_of_init(struct device_node *dp);
+int matrox_of_init(struct device_node *dp);
 #endif
 
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-#define mga_ydstorg(x)	ACCESS_FBINFO2(x, _mga_ydstorg)
-#define curr_ydstorg(x)	ACCESS_FBINFO2(x, _curr_ydstorg)
-#else
-#define mga_ydstorg(x) (0)
-#define curr_ydstorg(x) (0)
-#endif
+#define curr_ydstorg(x)	ACCESS_FBINFO2(x, curr.ydstorg.pixels)
 
 #define PCI_OPTION_REG	0x40
 #define PCI_MGA_INDEX	0x44
@@ -690,6 +713,9 @@
 #define M_DAC_VAL	(M_RAMDAC_BASE+1)
 #define M_PALETTE_MASK	(M_RAMDAC_BASE+2)
 
+#define M_X_INDEX	0x00
+#define M_X_DATAREG	0x0A
+
 #ifdef CONFIG_FB_MATROX_MILLENIUM
 #define TVP3026_INDEX		0x00
 #define TVP3026_PALWRADD	0x00
@@ -1021,19 +1047,21 @@
 #define isMilleniumII(x) (0)
 #endif
 
-static void matrox_cfbX_init(struct matrox_fb_info* minfo) {
+static void matrox_cfbX_init(WPMINFO struct display* p) {
 	u_int32_t maccess;
 	u_int32_t mpitch;
 	u_int32_t mopmode;
 
 	DBG("matrox_cfbX_init")
 	
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-	curr_ydstorg(MINFO) = mga_ydstorg(MINFO);
-#endif
-	mpitch = ACCESS_FBINFO(curr.var.xres_virtual);
-	
-	switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+	mpitch = p->var.xres_virtual;
+
+	if (p->type == FB_TYPE_TEXT) {
+		maccess = 0x00000000;
+		mpitch = (mpitch >> 4) | 0x8000; /* set something */
+		mopmode = M_OPMODE_8BPP;
+	} else {
+		switch (p->var.bits_per_pixel) {
 		case 4:		maccess = 0x00000000;	/* accelerate as 8bpp video */
 				mpitch = (mpitch >> 1) | 0x8000; /* disable linearization */
 				mopmode = M_OPMODE_4BPP;
@@ -1041,30 +1069,22 @@
     		case 8:		maccess = 0x00000000; 
 				mopmode = M_OPMODE_8BPP;
 				break;
-    		case 16:	if (ACCESS_FBINFO(curr.var.green.length) == 5)
+    		case 16:	if (p->var.green.length == 5)
 					maccess = 0xC0000001; 
 				else
     				    	maccess = 0x40000001; 
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-				curr_ydstorg(MINFO) >>= 1;
-#endif
 				mopmode = M_OPMODE_16BPP;
 				break;
 		case 24:	maccess = 0x00000003;
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-				curr_ydstorg(MINFO) /= 3;
-#endif
 				mopmode = M_OPMODE_24BPP;
 				break;
 		case 32:	maccess = 0x00000002; 
-#ifdef MATROX_2MB_WITH_4MB_ADDON
-				curr_ydstorg(MINFO) >>= 2;
-#endif
 				mopmode = M_OPMODE_32BPP;
 				break;
 		default:	maccess = 0x00000000; 
 				mopmode = 0x00000000;
 				break;	/* turn off acceleration!!! */
+		}
 	}
 	mga_fifo(8);
 	mga_outl(M_PITCH, mpitch);
@@ -1685,55 +1705,34 @@
 	}
 }
 
-#ifdef CONFIG_FB_MATROX_MILLENIUM
-static void outTi3026(CPMINFO int reg, int val) {
-	
-	DBG_REG("outTi3026")
-	
-	mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
-	mga_outb(M_RAMDAC_BASE+TVP3026_X_DATAREG, val);
-}
-
-static int inTi3026(CPMINFO int reg) {
-	
-	DBG_REG("inTi3026")
-	
-	mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, reg);
-	return mga_inb(M_RAMDAC_BASE+TVP3026_X_DATAREG);
+static void outDAC(CPMINFO int reg, int val) {
+	DBG_REG("outDAC");
+	mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+	mga_outb(M_RAMDAC_BASE+M_X_DATAREG, val);
 }
 
-#define POS3026_XCURCTRL	20
-
-static void matroxfb_ti3026_flashcursor(unsigned long ptr) {
-#define minfo ((struct matrox_fb_info*)ptr)
-	spin_lock(&ACCESS_FBINFO(lock.DAC));
-	outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA);
-	ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
-	add_timer(&ACCESS_FBINFO(cursor.timer));
-	spin_unlock(&ACCESS_FBINFO(lock.DAC));
-#undef minfo
+static int inDAC(CPMINFO int reg) {
+	DBG_REG("inDAC");
+	mga_outb(M_RAMDAC_BASE+M_X_INDEX, reg);
+	return mga_inb(M_RAMDAC_BASE+M_X_DATAREG);
 }
 
-static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
-	unsigned long flags;
-	u_int32_t xline;
-	unsigned int i;
-	unsigned int w, h;
-	unsigned int cd, cu;
-
-	if (ACCESS_FBINFO(currcon_display) != p)
-		return;
+#define outTi3026 outDAC
+#define inTi3026 inDAC
+#define outDAC1064 outDAC
+#define inDAC1064 inDAC
 
-	DBG("matroxfb_ti3026_createcursor");
+static void matroxfb_createcursorshape(WPMINFO struct display* p, int vmode) {
+	unsigned int h;
+	unsigned int cu, cd;
 
-	w = fontwidth(p);
 	h = fontheight(p);
 
-	if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+	if (vmode & FB_VMODE_DOUBLE)
 		h *= 2;
 	cd = h;
 	if (cd >= 10)
-		cd -= 1;
+		cd--;
 	switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
 		case CUR_NONE:
 				cu = cd;
@@ -1756,13 +1755,42 @@
 				cd = h;
 				break;
 	}
-	ACCESS_FBINFO(cursor.w) = w;
+	ACCESS_FBINFO(cursor.w) = fontwidth(p);
 	ACCESS_FBINFO(cursor.u) = cu;
 	ACCESS_FBINFO(cursor.d) = cd;
+}	
+
+#ifdef CONFIG_FB_MATROX_MILLENIUM
+#define POS3026_XCURCTRL	20
+
+static void matroxfb_ti3026_flashcursor(unsigned long ptr) {
+#define minfo ((struct matrox_fb_info*)ptr)
+	spin_lock(&ACCESS_FBINFO(lock.DAC));
+	outTi3026(PMINFO TVP3026_XCURCTRL, inTi3026(PMINFO TVP3026_XCURCTRL) ^ TVP3026_XCURCTRL_DIS ^ TVP3026_XCURCTRL_XGA);
+	ACCESS_FBINFO(cursor.timer.expires) = jiffies + HZ/2;
+	add_timer(&ACCESS_FBINFO(cursor.timer));
+	spin_unlock(&ACCESS_FBINFO(lock.DAC));
+#undef minfo
+}
+
+static void matroxfb_ti3026_createcursor(WPMINFO struct display* p) {
+	unsigned long flags;
+	u_int32_t xline;
+	unsigned int i;
+	unsigned int to;
+
+	if (ACCESS_FBINFO(currcon_display) != p)
+		return;
+
+	DBG("matroxfb_ti3026_createcursor");
+
+	matroxfb_createcursorshape(PMINFO p, p->var.vmode);
+
 	xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
 	spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
 	mga_outb(M_RAMDAC_BASE+TVP3026_INDEX, 0);
-	for (i = 0; i < cu; i++) {
+	to = ACCESS_FBINFO(cursor.u);
+	for (i = 0; i < to; i++) {
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
@@ -1772,7 +1800,8 @@
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, 0);
 	}
-	for (; i < cd; i++) {
+	to = ACCESS_FBINFO(cursor.d);
+	for (; i < to; i++) {
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 24);
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 16);
 		mga_outb(M_RAMDAC_BASE+TVP3026_CURRAMDATA, xline >> 8);
@@ -1818,10 +1847,11 @@
 	x *= fontwidth(p);
 	y *= fontheight(p);
 	y -= p->var.yoffset;
-	if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+	if (p->var.vmode & FB_VMODE_DOUBLE)
 		y *= 2;
 	spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
-	if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+	if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) {
+		ACCESS_FBINFO(cursor.redraw) = 0;
 		ACCESS_FBINFO(cursor.x) = x;
 		ACCESS_FBINFO(cursor.y) = y;
 		x += 64;
@@ -1851,21 +1881,6 @@
 #endif
 
 #ifdef NEED_DAC1064
-static void outDAC1064(CPMINFO int reg, int val) {
-
-	DBG_REG("outDAC1064");
-
-	mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
-	mga_outb(M_RAMDAC_BASE+M1064_X_DATAREG, val);
-}
-
-static int inDAC1064(CPMINFO int reg) {
-
-	DBG_REG("inDAC1064");
-
-	mga_outb(M_RAMDAC_BASE+M1064_INDEX, reg);
-	return mga_inb(M_RAMDAC_BASE+M1064_X_DATAREG);
-}
 
 static void matroxfb_DAC1064_flashcursor(unsigned long ptr) {
 #define minfo ((struct matrox_fb_info*)ptr)
@@ -1881,45 +1896,13 @@
 	vaddr_t cursorbase;
 	u_int32_t xline;
 	unsigned int i;
-	unsigned int w, h;
-	unsigned int cu, cd;
+	unsigned int h, to;
 
 	if (ACCESS_FBINFO(currcon_display) != p)
 		return;
 
-	w = fontwidth(p);
-	h = fontheight(p);
+	matroxfb_createcursorshape(PMINFO p, p->var.vmode);
 
-	if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
-		h *= 2;
-	cd = h;
-	if (cd >= 10)
-		cd -= 1;
-	switch (ACCESS_FBINFO(cursor.type) = (p->conp->vc_cursor_type & CUR_HWMASK)) {
-		case CUR_NONE:
-				cu = cd;
-				break;
-		case CUR_UNDERLINE:
-				cu = cd - 2;
-				break;
-		case CUR_LOWER_THIRD:
-				cu = (h * 2) / 3;
-				break;
-		case CUR_LOWER_HALF:
-				cu = h / 2;
-				break;
-		case CUR_TWO_THIRDS:
-				cu = h / 3;
-				break;
-		case CUR_BLOCK:
-		default:
-				cu = 0;
-				cd = h;
-				break;
-	}
-	ACCESS_FBINFO(cursor.w) = w;
-	ACCESS_FBINFO(cursor.u) = cu;
-	ACCESS_FBINFO(cursor.d) = cd;
 	xline = (~0) << (32 - ACCESS_FBINFO(cursor.w));
 	cursorbase = ACCESS_FBINFO(video.vbase);
 	h = ACCESS_FBINFO(features.DAC1064.cursorimage);
@@ -1927,14 +1910,16 @@
 	WaitTillIdle();
 	mga_outl(M_OPMODE, M_OPMODE_32BPP);
 #endif
-	for (i = 0; i < cu; i++) {
+	to = ACCESS_FBINFO(cursor.u);
+	for (i = 0; i < to; i++) {
 		mga_writel(cursorbase, h, 0);
 		mga_writel(cursorbase, h+4, 0);
 		mga_writel(cursorbase, h+8, ~0);
 		mga_writel(cursorbase, h+12, ~0);
 		h += 16;
 	}
-	for (; i < cd; i++) {
+	to = ACCESS_FBINFO(cursor.d);
+	for (; i < to; i++) {
 		mga_writel(cursorbase, h, 0);
 		mga_writel(cursorbase, h+4, xline);
 		mga_writel(cursorbase, h+8, ~0);
@@ -1972,10 +1957,11 @@
 	x *= fontwidth(p);
 	y *= fontheight(p);
 	y -= p->var.yoffset;
-	if (ACCESS_FBINFO(curr.var.vmode) & FB_VMODE_DOUBLE)
+	if (p->var.vmode & FB_VMODE_DOUBLE)
 		y *= 2;
 	spin_lock_irqsave(&ACCESS_FBINFO(lock.DAC), flags);
-	if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y))) {
+	if ((x != ACCESS_FBINFO(cursor.x)) || (y != ACCESS_FBINFO(cursor.y)) || ACCESS_FBINFO(cursor.redraw)) {
+		ACCESS_FBINFO(cursor.redraw) = 0;
 		ACCESS_FBINFO(cursor.x) = x;
 		ACCESS_FBINFO(cursor.y) = y;
 		x += 64;
@@ -2109,6 +2095,218 @@
 	return 1;
 }
 
+static void matrox_text_setup(struct display* p) {
+	MINFO_FROM_DISP(p);
+
+	p->next_line = p->line_length ? p->line_length : ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
+	p->next_plane = 0;
+}
+
+static void matrox_text_bmove(struct display* p, int sy, int sx, int dy, int dx,
+		int height, int width) {
+	unsigned int srcoff;
+	unsigned int dstoff;
+	unsigned int step;
+	MINFO_FROM_DISP(p);
+
+	step = ACCESS_FBINFO(devflags.textstep);
+	srcoff = (sy * p->next_line) + (sx * step);
+	dstoff = (dy * p->next_line) + (dx * step);
+	if (dstoff < srcoff) {
+		while (height > 0) {
+			int i;
+			for (i = width; i > 0; dstoff += step, srcoff += step, i--)
+				mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
+			height--;
+			dstoff += p->next_line - width * step;
+			srcoff += p->next_line - width * step;
+		}
+	} else {
+		unsigned int off;
+
+		off = (height - 1) * p->next_line + (width - 1) * step;
+		srcoff += off;
+		dstoff += off;
+		while (height > 0) {
+			int i;
+			for (i = width; i > 0; dstoff -= step, srcoff -= step, i--)
+				mga_writew(ACCESS_FBINFO(video.vbase), dstoff, mga_readw(ACCESS_FBINFO(video.vbase), srcoff));
+			dstoff -= p->next_line - width * step;
+			srcoff -= p->next_line - width * step;
+			height--;
+		}
+	}
+}
+
+static void matrox_text_clear(struct vc_data* conp, struct display* p, int sy, int sx,
+		int height, int width) {
+	unsigned int offs;
+	unsigned int val;
+	unsigned int step;
+	MINFO_FROM_DISP(p);
+
+	step = ACCESS_FBINFO(devflags.textstep);
+	offs = sy * p->next_line + sx * step;
+	val = ntohs((attr_bgcol(p, conp->vc_video_erase_char) << 4) | attr_fgcol(p, conp->vc_video_erase_char) | (' ' << 8));
+	while (height > 0) {
+		int i;
+		for (i = width; i > 0; offs += step, i--)
+			mga_writew(ACCESS_FBINFO(video.vbase), offs, val);
+		offs += p->next_line - width * step;
+		height--;
+	}
+}
+
+static void matrox_text_putc(struct vc_data* conp, struct display* p, int c, int yy, int xx) {
+	unsigned int offs;
+	unsigned int chr;
+	unsigned int step;
+	MINFO_FROM_DISP(p);
+
+	step = ACCESS_FBINFO(devflags.textstep);
+	offs = yy * p->next_line + xx * step;
+	chr = attr_fgcol(p,c) | (attr_bgcol(p,c) << 4) | ((c & p->charmask) << 8);
+	if (chr & 0x10000) chr |= 0x08;
+	mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(chr));
+}
+
+static void matrox_text_putcs(struct vc_data* conp, struct display* p, const unsigned short* s,
+		int count, int yy, int xx) {
+	unsigned int offs;
+	unsigned int attr;
+	unsigned int step;
+	MINFO_FROM_DISP(p);
+
+	step = ACCESS_FBINFO(devflags.textstep);
+	offs = yy * p->next_line + xx * step;
+	attr = attr_fgcol(p,*s) | (attr_bgcol(p,*s) << 4);
+	while (count-- > 0) {
+		unsigned int chr = ((*s++) & p->charmask) << 8;
+		if (chr & 0x10000) chr ^= 0x10008;
+		mga_writew(ACCESS_FBINFO(video.vbase), offs, ntohs(attr|chr));
+		offs += step;
+	}
+}
+
+static void matrox_text_revc(struct display* p, int xx, int yy) {
+	unsigned int offs;
+	unsigned int step;
+	MINFO_FROM_DISP(p);
+
+	step = ACCESS_FBINFO(devflags.textstep);
+	offs = yy * p->next_line + xx * step + 1;
+	mga_writeb(ACCESS_FBINFO(video.vbase), offs, mga_readb(ACCESS_FBINFO(video.vbase), offs) ^ 0x77);
+}
+
+static int matrox_text_loadfont(WPMINFO struct display* p) {
+	unsigned int fsize;
+	unsigned int width;
+	vaddr_t dst;
+	unsigned int i;
+	u_int8_t* font;
+
+	if (!p || !p->fontdata)
+		return 0;
+	width = fontwidth(p);
+	fsize = p->userfont?FNTCHARCNT(p->fontdata):256;
+
+	dst = ACCESS_FBINFO(video.vbase);
+	i = 2;
+	font = (u_int8_t*)p->fontdata;
+	mga_setr(M_SEQ_INDEX, 0x02, 0x04);
+	while (fsize--) {
+		int l;
+
+		for (l = 0; l < fontheight(p); l++) {
+			mga_writeb(dst, i, *font++);
+			if (fontwidth(p) > 8) font++;
+			i += ACCESS_FBINFO(devflags.vgastep);
+		}
+		i += (32 - fontheight(p)) * ACCESS_FBINFO(devflags.vgastep);
+	}
+	mga_setr(M_SEQ_INDEX, 0x02, 0x03);
+	return 1;
+}
+
+static void matrox_text_createcursor(WPMINFO struct display* p) {
+
+	if (ACCESS_FBINFO(currcon_display) != p)
+		return;
+
+	matroxfb_createcursorshape(PMINFO p, 0);
+	mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
+	mga_setr(M_CRTC_INDEX, 0x0B, ACCESS_FBINFO(cursor.d) - 1);
+}
+
+static void matrox_text_cursor(struct display* p, int mode, int x, int y) {
+	unsigned int pos;
+	MINFO_FROM_DISP(p);
+
+	if (mode == CM_ERASE) {
+		if (ACCESS_FBINFO(cursor.state) != CM_ERASE) {
+			mga_setr(M_CRTC_INDEX, 0x0A, 0x20);
+			ACCESS_FBINFO(cursor.state) = CM_ERASE;
+		}
+		return;
+	}
+	if ((p->conp->vc_cursor_type & CUR_HWMASK) != ACCESS_FBINFO(cursor.type))
+		matrox_text_createcursor(PMINFO p);
+
+	/* DO NOT CHECK cursor.x != x because of vgaHWinit moves cursor to 0,0 */
+	ACCESS_FBINFO(cursor.x) = x;
+	ACCESS_FBINFO(cursor.y) = y;
+	pos = p->next_line / ACCESS_FBINFO(devflags.textstep) * y + x;
+	mga_setr(M_CRTC_INDEX, 0x0F, pos);
+	mga_setr(M_CRTC_INDEX, 0x0E, pos >> 8);
+
+	mga_setr(M_CRTC_INDEX, 0x0A, ACCESS_FBINFO(cursor.u));
+	ACCESS_FBINFO(cursor.state) = CM_DRAW;
+}
+
+static void matrox_text_round(CPMINFO struct fb_var_screeninfo* var, struct display* p) {
+	unsigned hf;
+	unsigned vf;
+	unsigned vxres;
+	unsigned ych;
+
+	hf = fontwidth(p);
+	if (!hf) hf = 8;
+	/* do not touch xres */
+	vxres = (var->xres_virtual + hf - 1) / hf;
+	if (vxres >= 256)
+		vxres = 255;
+	if (vxres < 16)
+		vxres = 16;
+	vxres = (vxres + 1) & ~1;	/* must be even */
+	vf = fontheight(p);
+	if (!vf) vf = 16;
+	if (var->yres < var->yres_virtual) {
+		ych = ACCESS_FBINFO(devflags.textvram) / vxres;
+		var->yres_virtual = ych * vf;
+	} else
+		ych = var->yres_virtual / vf;
+	if (vxres * ych > ACCESS_FBINFO(devflags.textvram)) {
+		ych = ACCESS_FBINFO(devflags.textvram) / vxres;
+		var->yres_virtual = ych * vf;
+	}
+	var->xres_virtual = vxres * hf;
+}
+
+static int matrox_text_setfont(struct display* p, int width, int height) {
+	DBG("matrox_text_setfont");
+
+	if (p) {
+		MINFO_FROM_DISP(p);
+		
+		matrox_text_round(PMINFO &p->var, p);
+		p->next_line = p->line_length = ((p->var.xres_virtual / (fontwidth(p)?fontwidth(p):8)) * ACCESS_FBINFO(devflags.textstep));
+
+		if (p->conp)
+			matrox_text_createcursor(PMINFO p);
+	}
+	return 0;
+}
+
 #define matrox_cfb16_revc matrox_cfbX_revc
 #define matrox_cfb24_revc matrox_cfbX_revc
 #define matrox_cfb32_revc matrox_cfbX_revc
@@ -2117,6 +2315,15 @@
 #define matrox_cfb24_putc matrox_cfb32_putc
 #define matrox_cfb24_putcs matrox_cfb32_putcs
 
+#ifdef FBCON_HAS_VGATEXT
+static struct display_switch matroxfb_text = {
+	matrox_text_setup,    matrox_text_bmove,  matrox_text_clear,
+	matrox_text_putc,     matrox_text_putcs,  matrox_text_revc,
+	matrox_text_cursor,   matrox_text_setfont, NULL,
+	FONTWIDTH(8)|FONTWIDTH(9)
+};
+#endif
+
 #ifdef FBCON_HAS_CFB4
 static struct display_switch matroxfb_cfb4 = {
 	fbcon_cfb4_setup,     matrox_cfb4_bmove,  matrox_cfb4_clear,
@@ -2178,7 +2385,10 @@
 	
 	p->dispsw_data = NULL;
 	if ((p->var.accel_flags & FB_ACCELF_TEXT) != FB_ACCELF_TEXT) {
-		switch (p->var.bits_per_pixel) {
+		if (p->type == FB_TYPE_TEXT) {
+			swtmp = &matroxfb_text;
+		} else {
+			switch (p->var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB4
 			case 4:
 				swtmp = &fbcon_cfb4;
@@ -2210,12 +2420,16 @@
 			default:
 				p->dispsw = &fbcon_dummy;
 				return;
+			}
 		}
 		dprintk(KERN_INFO "matroxfb: acceleration disabled\n");
 		p->dispsw = swtmp;
 		return;
 	}
-	switch (p->var.bits_per_pixel) {
+	if (p->type == FB_TYPE_TEXT) {
+		swtmp = &matroxfb_text;
+	} else {
+		switch (p->var.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB4
 		case 4:
 			swtmp = &matroxfb_cfb4;
@@ -2247,11 +2461,12 @@
 		default:
 			p->dispsw = &fbcon_dummy;
 			return;
+		}
 	}
 	dprintk(KERN_INFO "matroxfb: now accelerated\n");
 	memcpy(&ACCESS_FBINFO(dispsw), swtmp, sizeof(ACCESS_FBINFO(dispsw)));
 	p->dispsw = &ACCESS_FBINFO(dispsw);
-	if (ACCESS_FBINFO(devflags.hwcursor)) {
+	if ((p->type != FB_TYPE_TEXT) && ACCESS_FBINFO(devflags.hwcursor)) {
 		if (isMillenium(MINFO)) {
 #ifdef CONFIG_FB_MATROX_MILLENIUM
 			ACCESS_FBINFO(dispsw.cursor) = matroxfb_ti3026_cursor;
@@ -2298,27 +2513,19 @@
 /* --------------------------------------------------------------------- */
 
 static void matrox_pan_var(WPMINFO struct fb_var_screeninfo *var) {
-	struct matroxfb_par* p = &ACCESS_FBINFO(curr);
 	unsigned int pos;
 	unsigned short p0, p1, p2;
+	struct display *disp;
 
 	DBG("matrox_pan_var")
 	
-	p->var.xoffset = var->xoffset;
-	p->var.yoffset = var->yoffset;
-	if (var->vmode & FB_VMODE_YWRAP)
-		p->var.vmode |= FB_VMODE_YWRAP;
-	else
-		p->var.vmode &= ~FB_VMODE_YWRAP;
-	
-	pos = (p->var.yoffset * p->var.xres_virtual + p->var.xoffset) * p->final_bppShift / 32;
-	if (mga_ydstorg(MINFO)) {
-		if (isInterleave(MINFO))
-			pos += mga_ydstorg(MINFO) >> 3;
-		else
-			pos += mga_ydstorg(MINFO) >> 2;
+	disp = ACCESS_FBINFO(currcon_display);
+	if (disp->type == FB_TYPE_TEXT) {
+		pos = var->yoffset / fontheight(disp) * disp->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(disp)?fontwidth(disp):8);
+	} else {
+		pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+		pos += ACCESS_FBINFO(curr.ydstorg.chunks);
 	}
-
 	p0 = ACCESS_FBINFO(currenthw)->CRTC[0x0D] = pos & 0xFF;
 	p1 = ACCESS_FBINFO(currenthw)->CRTC[0x0C] = (pos & 0xFF00) >> 8;
 	p2 = ACCESS_FBINFO(currenthw)->CRTCEXT[0] = (ACCESS_FBINFO(currenthw)->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
@@ -2392,6 +2599,9 @@
 	DBG("matroxfb_get_final_bppShift")
 	
 	bppshft2 = bpp;
+	if (!bppshft2) {
+		return 8;
+	}
 	if (isInterleave(MINFO))
 		bppshft2 >>= 1;
 	if (ACCESS_FBINFO(devflags.video64bits))
@@ -2406,6 +2616,7 @@
 	DBG("matroxfb_test_and_set_rounding")
 	
 	switch (bpp) {
+		case 0:		return xres;
 		case 4:		rounding = 128;
 				break;
 		case 8:		rounding = 64;
@@ -2431,6 +2642,8 @@
 	int xres_new;
 
 	DBG("matroxfb_pitch_adjust")
+
+	if (!bpp) return xres;
 	
 	width = ACCESS_FBINFO(capable.vxres);
 
@@ -2584,10 +2797,9 @@
 	return fvco;
 }
 
-static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, int Bpp) {
+static int Ti3026_setpclk(CPMINFO struct matrox_hw_state* hw, int clk, struct display* p) {
 	unsigned int f_pll;
 	unsigned int pixfeed, pixin, pixpost;
-	unsigned int loopfeed, loopin, looppost, loopdiv, z;
 	
 	DBG("Ti3026_setpclk")
 	
@@ -2596,52 +2808,65 @@
 	hw->DACclk[0] = pixin | 0xC0;
 	hw->DACclk[1] = pixfeed;
 	hw->DACclk[2] = pixpost | 0xB0;
-	if (ACCESS_FBINFO(curr.var.bits_per_pixel) == 24) {
-		loopfeed = 3;		/* set lm to any possible value */
-		loopin = 3 * 32 / Bpp;
+
+	if (p->type == FB_TYPE_TEXT) {
+		hw->DACreg[POS3026_XMEMPLLCTRL] = TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_PIXPLL;
+		hw->DACclk[3] = 0xFD;
+		hw->DACclk[4] = 0x3D;
+		hw->DACclk[5] = 0x70;
 	} else {
-		loopfeed = 4;
-		loopin = 4 * 32 / Bpp;
-	}
-	z = (110000 * loopin) / (f_pll * loopfeed);
-	loopdiv = 0; /* div 2 */
-	if (z < 2)
-		looppost = 0;
-	else if (z < 4)
-		looppost = 1;
-	else if (z < 8)
-		looppost = 2;
-	else {
-		looppost = 3;
-		loopdiv = z/16; 
-	}
-	if (ACCESS_FBINFO(curr.var.bits_per_pixel) == 24) {
-		hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
-		hw->DACclk[4] = (65 - loopfeed) | 0x80;
-		if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) {
-			if (isInterleave(MINFO))
-				hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
-			else {
-				hw->DACclk[4] &= ~0xC0;
-				hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
-			}
+		unsigned int loopfeed, loopin, looppost, loopdiv, z;
+		unsigned int Bpp;
+
+		Bpp = ACCESS_FBINFO(curr.final_bppShift);
+
+		if (p->var.bits_per_pixel == 24) {
+			loopfeed = 3;		/* set lm to any possible value */
+			loopin = 3 * 32 / Bpp;
 		} else {
-			if (isInterleave(MINFO))
-				;	/* default... */
-			else {
-				hw->DACclk[4] ^= 0xC0;	/* change from 0x80 to 0x40 */
-				hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+			loopfeed = 4;
+			loopin = 4 * 32 / Bpp;
+		}
+		z = (110000 * loopin) / (f_pll * loopfeed);
+		loopdiv = 0; /* div 2 */
+		if (z < 2)
+			looppost = 0;
+		else if (z < 4)
+			looppost = 1;
+		else if (z < 8)
+			looppost = 2;
+		else {
+			looppost = 3;
+			loopdiv = z/16; 
+		}
+		if (p->var.bits_per_pixel == 24) {
+			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+			hw->DACclk[4] = (65 - loopfeed) | 0x80;
+			if (ACCESS_FBINFO(accel.ramdac_rev) > 0x20) {
+				if (isInterleave(MINFO))
+					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_8_3;
+				else {
+					hw->DACclk[4] &= ~0xC0;
+					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026B_XLATCHCTRL_4_3;
+				}
+			} else {
+				if (isInterleave(MINFO))
+					;	/* default... */
+				else {
+					hw->DACclk[4] ^= 0xC0;	/* change from 0x80 to 0x40 */
+					hw->DACreg[POS3026_XLATCHCTRL] = TVP3026A_XLATCHCTRL_4_3;
+				}
 			}
+			hw->DACclk[5] = looppost | 0xF8;
+			if (ACCESS_FBINFO(devflags.mga_24bpp_fix))
+				hw->DACclk[5] ^= 0x40;
+		} else {
+			hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
+			hw->DACclk[4] = 65 - loopfeed;
+			hw->DACclk[5] = looppost | 0xF0;
 		}
-		hw->DACclk[5] = looppost | 0xF8;
-		if (ACCESS_FBINFO(devflags.mga_24bpp_fix))
-			hw->DACclk[5] ^= 0x40;
-	} else {
-		hw->DACclk[3] = ((65 - loopin) & 0x3F) | 0xC0;
-		hw->DACclk[4] = 65 - loopfeed;
-		hw->DACclk[5] = looppost | 0xF0;
+		hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
 	}
-	hw->DACreg[POS3026_XMEMPLLCTRL] = loopdiv | TVP3026_XMEMPLLCTRL_STROBEMKC4 | TVP3026_XMEMPLLCTRL_MCLK_MCLKPLL | TVP3026_XMEMPLLCTRL_RCLK_LOOPPLL;
 	return 0;
 }
 #endif
@@ -2667,20 +2892,34 @@
 	mt->sync = var->sync;
 }
 
-static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int vgaHWinit(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
 	unsigned int hd, hs, he, hbe, ht;
 	unsigned int vd, vs, ve, vt;
 	unsigned int wd;
 	unsigned int divider;
 	int i;
+	int text = p->type == FB_TYPE_TEXT;
+	int fwidth;
+
+	if (text) {
+		fwidth = fontwidth(p);
+		if (!fwidth) fwidth = 8;
+	} else
+		fwidth = 8;
 
 	DBG("vgaHWinit")
 	
 	hw->SEQ[0] = 0x00;
-	hw->SEQ[1] = 0x01;	/* or 0x09 */
+	if (fwidth == 9)
+		hw->SEQ[1] = 0x00;
+	else
+		hw->SEQ[1] = 0x01;	/* or 0x09 */
 	hw->SEQ[2] = 0x0F;	/* bitplanes */
 	hw->SEQ[3] = 0x00;
-	hw->SEQ[4] = 0x0E;
+	if (text)
+		hw->SEQ[4] = 0x02;
+	else
+		hw->SEQ[4] = 0x0E;
 	/* CRTC 0..7, 9, 16..19, 21, 22 are reprogrammed by Matrox Millenium code... Hope that by MGA1064 too */
 	if (m->dblscan) {
 		m->VTotal <<= 1;
@@ -2701,28 +2940,48 @@
 	hw->GCTL[2] = 0x00;
 	hw->GCTL[3] = 0x00;
 	hw->GCTL[4] = 0x00;
-	hw->GCTL[5] = 0x40;
-	hw->GCTL[6] = 0x05;
+	if (text) {
+		hw->GCTL[5] = 0x10;
+		hw->GCTL[6] = 0x02;
+	} else {
+		hw->GCTL[5] = 0x40;
+		hw->GCTL[6] = 0x05;
+	}
 	hw->GCTL[7] = 0x0F;
 	hw->GCTL[8] = 0xFF;
 
 	/* Whole ATTR is ignored in PowerGraphics mode */
 	for (i = 0; i < 16; i++)
 		hw->ATTR[i] = i;
-	hw->ATTR[16] = 0x41;
+	if (text) {
+		hw->ATTR[16] = 0x04;
+	} else {
+		hw->ATTR[16] = 0x41;
+	}
 	hw->ATTR[17] = 0xFF;
 	hw->ATTR[18] = 0x0F;
-	hw->ATTR[19] = 0x00;
+	if (fwidth == 9)
+		hw->ATTR[19] = 0x08;
+	else
+		hw->ATTR[19] = 0x00;
 	hw->ATTR[20] = 0x00;
 
-	hd = m->HDisplay >> 3;
-	hs = m->HSyncStart >> 3;
-	he = m->HSyncEnd >> 3;
-	ht = m->HTotal >> 3;
-	/* standard timmings are in 8pixels, but for interleaved we cannot */
-	/* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
-	/* using 16 or more pixels per unit can save us */
-	divider = ACCESS_FBINFO(curr.final_bppShift);
+	if (text) {
+		hd = m->HDisplay / fwidth;
+		hs = m->HSyncStart / fwidth;
+		he = m->HSyncEnd / fwidth;
+		ht = m->HTotal / fwidth;
+		divider = 8;
+	} else {
+		hd = m->HDisplay >> 3;
+		hs = m->HSyncStart >> 3;
+		he = m->HSyncEnd >> 3;
+		ht = m->HTotal >> 3;
+		/* standard timmings are in 8pixels, but for interleaved we cannot */
+		/* do it for 4bpp (because of (4bpp >> 1(interleaved))/4 == 0) */
+		/* using 16 or more pixels per unit can save us */
+		divider = ACCESS_FBINFO(curr.final_bppShift);
+	}
 	while (divider & 3) {
 		hd >>= 1;
 		hs >>= 1;
@@ -2747,10 +3006,16 @@
 	vs = m->VSyncStart - 1;
 	ve = m->VSyncEnd - 1;
 	vt = m->VTotal - 2;
-	if (((ht & 0x0F) == 0x0E) || ((ht & 0x0F) == 0x04))
+	/* G200 cannot work with (ht & 7) == 6 */
+	if (((ht & 0x07) == 0x06) || ((ht & 0x0F) == 0x04))
 		ht++;
-	hbe = ht;
-	wd = ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.final_bppShift) / 64;
+	if (text) {
+		hbe = ht - 1;
+		wd = p->var.xres_virtual / (fwidth * 2);
+	} else {
+		hbe = ht;
+		wd = p->var.xres_virtual * ACCESS_FBINFO(curr.final_bppShift) / 64;
+	}
 
 	hw->CRTCEXT[0] = 0;
 	hw->CRTCEXT[5] = 0;
@@ -2770,7 +3035,10 @@
 			  ((vd & 0x400) >>  8) |	/* disp end */
 			  ((vd & 0xC00) >>  7) |	/* vblanking start */
 			  ((vs & 0xC00) >>  5);
-	hw->CRTCEXT[3] = (divider - 1) | 0x80;
+	if (text)
+		hw->CRTCEXT[3] = 0x00;
+	else
+		hw->CRTCEXT[3] = (divider - 1) | 0x80;
 	hw->CRTCEXT[4] = 0;
 
 	hw->CRTC[0] = ht-4;
@@ -2779,6 +3047,8 @@
 	hw->CRTC[3] = (hbe & 0x1F) | 0x80;
 	hw->CRTC[4] = hs;
 	hw->CRTC[5] = ((hbe & 0x20) << 2) | (he & 0x1F);
+	if (text)
+		hw->CRTC[5] |= 0x60;	/* delay sync for 3 clocks (to same picture position on MGA and VGA) */
 	hw->CRTC[6] = vt & 0xFF;
 	hw->CRTC[7] = ((vt & 0x100) >> 8) |
 		      ((vd & 0x100) >> 7) |
@@ -2790,6 +3060,8 @@
 		      ((vs & 0x200) >> 2);
 	hw->CRTC[8] = 0x00;
 	hw->CRTC[9] = ((vd & 0x200) >> 4) | 0x40;
+	if (text)
+		hw->CRTC[9] |= fontheight(p) - 1;
 	if (m->dblscan && !m->interlaced)
 		hw->CRTC[9] |= 0x80;
 	for (i = 10; i < 16; i++)
@@ -2801,7 +3073,17 @@
 	hw->CRTC[20] = 0x00;
 	hw->CRTC[21] = vd /* & 0xFF */;
 	hw->CRTC[22] = (vt + 1) /* & 0xFF */;
-	hw->CRTC[23] = 0xC3;
+	if (text) {
+		if (ACCESS_FBINFO(devflags.textmode) == 1)
+			hw->CRTC[23] = 0xC3;
+		else
+			hw->CRTC[23] = 0xA3;
+		if (ACCESS_FBINFO(devflags.textmode) == 4)
+			hw->CRTC[20] = 0x5F;
+		else
+			hw->CRTC[20] = 0x1F;
+	} else
+		hw->CRTC[23] = 0xC3;
 	hw->CRTC[24] = 0xFF;
 	return 0;
 };
@@ -2824,6 +3106,7 @@
 #define POS1064_XVREFCTRL		12
 #define POS1064_XMULCTRL		13
 #define POS1064_XGENCTRL		15
+#define POS1064_XMISCCTRL		16
 
 static const unsigned char MGA1064_DAC[] = {
 		0x00, 0x00, M1064_XCURCTRL_DIS,
@@ -2853,7 +3136,14 @@
 	u_int32_t mx;
 
 	DBG("DAC1064_setmclk")
-	
+
+	if (ACCESS_FBINFO(devflags.noinit)) {
+		/* read MCLK and give up... */
+		hw->DACclk[3] = inDAC1064(PMINFO DAC1064_XSYSPLLM);
+		hw->DACclk[4] = inDAC1064(PMINFO DAC1064_XSYSPLLN);
+		hw->DACclk[5] = inDAC1064(PMINFO DAC1064_XSYSPLLP);
+		return;
+	}
 	mx = hw->MXoptionReg | 0x00000004;
 	pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, mx);
 	mx &= ~0x000000BB;
@@ -2903,18 +3193,26 @@
 	hw->MXoptionReg = mx;
 }
 
-static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int DAC1064_init_1(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display *p) {
 	
 	DBG("DAC1064_init_1")
 	
 	memcpy(hw->DACreg, MGA1064_DAC, sizeof(MGA1064_DAC_regs));
-	switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+	if (p->type == FB_TYPE_TEXT) {
+		hw->DACreg[POS1064_XMISCCTRL] = M1064_XMISCCTRL_DAC_EN
+					      | M1064_XMISCCTRL_MFC_VGA
+					      | M1064_XMISCCTRL_DAC_6BIT
+					      | M1064_XMISCCTRL_LUT_EN;
+		hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP 
+				             | M1064_XMULCTRL_GRAPHICS_PALETIZED;
+	} else {
+		switch (p->var.bits_per_pixel) {
 		/* case 4: not supported by MGA1064 DAC */
 		case 8:	
 			hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_8BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 			break;
 		case 16:
-			if (ACCESS_FBINFO(curr.var.green.length) == 5)
+			if (p->var.green.length == 5)
 				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_15BPP_1BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
 			else
 				hw->DACreg[POS1064_XMULCTRL] = M1064_XMULCTRL_DEPTH_16BPP | M1064_XMULCTRL_GRAPHICS_PALETIZED;
@@ -2927,6 +3225,7 @@
 			break;
 		default:
 			return 1;	/* unsupported depth */
+		}
 	}
 	hw->DACreg[POS1064_XVREFCTRL] = ACCESS_FBINFO(features.DAC1064.xvrefctrl);
 	hw->DACreg[POS1064_XGENCTRL] &= ~M1064_XGENCTRL_SYNC_ON_GREEN_MASK;
@@ -2936,12 +3235,12 @@
 	return 0;
 }
 
-static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int DAC1064_init_2(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
 	
 	DBG("DAC1064_init_2")
 	
 	DAC1064_setpclk(PMINFO hw, m->pixclock);
-	if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 16) {	/* 256 entries */
+	if (p->var.bits_per_pixel > 16) {	/* 256 entries */
 		int i;
 
 		for (i = 0; i < 256; i++) {
@@ -2949,8 +3248,8 @@
 			hw->DACpal[i * 3 + 1] = i;
 			hw->DACpal[i * 3 + 2] = i;
 		}
-	} else if (ACCESS_FBINFO(curr.var.bits_per_pixel) > 8) {
-		if (ACCESS_FBINFO(curr.var.green.length) == 5) {	/* 0..31, 128..159 */
+	} else if (p->var.bits_per_pixel > 8) {
+		if (p->var.green.length == 5) {	/* 0..31, 128..159 */
 			int i;
 
 			for (i = 0; i < 32; i++) {
@@ -2995,15 +3294,29 @@
 
 static void DAC1064_restore_2(WPMINFO const struct matrox_hw_state* hw, const struct matrox_hw_state* oldhw, struct display* p) {
 	unsigned int i;
+	unsigned int tmout;
 	
 	DBG("DAC1064_restore_2")
 	
 	for (i = 0; i < 3; i++)
 		outDAC1064(PMINFO M1064_XPIXPLLCM + i, hw->DACclk[i]);
-	while (!(inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40));
+	for (tmout = 500000; tmout; tmout--) {
+		if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
+			break;
+		udelay(10);
+	};
+	if (!tmout)
+		printk(KERN_ERR "matroxfb: Pixel PLL not locked after 5 secs\n");
+
 	if (p && p->conp) {
-		matroxfb_DAC1064_createcursor(PMINFO p);
-		i = matroxfb_fastfont_tryset(PMINFO p);
+		if (p->type == FB_TYPE_TEXT) {
+			matrox_text_createcursor(PMINFO p);
+			matrox_text_loadfont(PMINFO p);
+			i = 0;
+		} else {
+			matroxfb_DAC1064_createcursor(PMINFO p);
+			i = matroxfb_fastfont_tryset(PMINFO p);
+		}
 	} else
 		i = 0;
 	if (i) {
@@ -3028,12 +3341,12 @@
 #endif /* NEED_DAC1064 */
 
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
-static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int MGA1064_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
 	
 	DBG("MGA1064_init")
 	
-	if (DAC1064_init_1(PMINFO hw, m)) return 1;
-	if (vgaHWinit(PMINFO hw, m)) return 1;
+	if (DAC1064_init_1(PMINFO hw, m, p)) return 1;
+	if (vgaHWinit(PMINFO hw, m, p)) return 1;
 
 	hw->MiscOutReg = 0xCB;
 	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -3043,19 +3356,19 @@
 	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
 		hw->CRTCEXT[3] |= 0x40;
 
-	if (DAC1064_init_2(PMINFO hw, m)) return 1;
+	if (DAC1064_init_2(PMINFO hw, m, p)) return 1;
 	return 0;		
 }
 #endif
 
 #ifdef CONFIG_FB_MATROX_G100
-static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int MGAG100_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
 
 	DBG("MGAG100_init")
 
-	if (DAC1064_init_1(PMINFO hw, m)) return 1;
+	if (DAC1064_init_1(PMINFO hw, m, p)) return 1;
 	hw->MXoptionReg &= ~0x2000;
-	if (vgaHWinit(PMINFO hw, m)) return 1;
+	if (vgaHWinit(PMINFO hw, m, p)) return 1;
 
 	hw->MiscOutReg = 0xEF;
 	if (m->sync & FB_SYNC_HOR_HIGH_ACT)
@@ -3065,19 +3378,27 @@
 	if (m->sync & FB_SYNC_COMP_HIGH_ACT) /* should be only FB_SYNC_COMP */
 		hw->CRTCEXT[3] |= 0x40;
 
-	if (DAC1064_init_2(PMINFO hw, m)) return 1;
+	if (DAC1064_init_2(PMINFO hw, m, p)) return 1;
 	return 0;		
 }
 #endif	/* G100 */
 
 #ifdef CONFIG_FB_MATROX_MILLENIUM
-static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m) {
+static int Ti3026_init(CPMINFO struct matrox_hw_state* hw, struct my_timming* m, struct display* p) {
 	u_int8_t muxctrl = isInterleave(MINFO) ? TVP3026_XMUXCTRL_MEMORY_64BIT : TVP3026_XMUXCTRL_MEMORY_32BIT;
 
 	DBG("Ti3026_init")
 
 	memcpy(hw->DACreg, MGADACbpp32, sizeof(hw->DACreg));
-	switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
+	if (p->type == FB_TYPE_TEXT) {
+		hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_8_1;
+		hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
+		hw->DACreg[POS3026_XMUXCTRL] = TVP3026_XMUXCTRL_VGA;
+		hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | 
+					       TVP3026_XCLKCTRL_DIV4;
+		hw->DACreg[POS3026_XMISCCTRL] = TVP3026_XMISCCTRL_DAC_PUP | TVP3026_XMISCCTRL_DAC_6BIT | TVP3026_XMISCCTRL_PSEL_DIS | TVP3026_XMISCCTRL_PSEL_LOW;
+	} else {
+		switch (p->var.bits_per_pixel) {
 		case 4:	hw->DACreg[POS3026_XLATCHCTRL] = TVP3026_XLATCHCTRL_16_1;	/* or _8_1, they are same */
 			hw->DACreg[POS3026_XTRUECOLORCTRL] = TVP3026_XTRUECOLORCTRL_PSEUDOCOLOR;
 			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_4BIT;
@@ -3092,7 +3413,7 @@
 			break;
 		case 16:
 			/* XLATCHCTRL should be _4_1 / _2_1... Why is not? (_2_1 is used everytime) */
-			hw->DACreg[POS3026_XTRUECOLORCTRL] = (ACCESS_FBINFO(curr.var.green.length) == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
+			hw->DACreg[POS3026_XTRUECOLORCTRL] = (p->var.green.length == 5)? (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_ORGB_1555 ) : (TVP3026_XTRUECOLORCTRL_DIRECTCOLOR | TVP3026_XTRUECOLORCTRL_RGB_565);
 			hw->DACreg[POS3026_XMUXCTRL] = muxctrl | TVP3026_XMUXCTRL_PIXEL_16BIT;
 			hw->DACreg[POS3026_XCLKCTRL] = TVP3026_XCLKCTRL_SRC_PLL | TVP3026_XCLKCTRL_DIV2;
 			break;
@@ -3108,8 +3429,9 @@
 			break;
 		default:
 			return 1;	/* TODO: failed */
+		}
 	}
-	if (vgaHWinit(PMINFO hw, m)) return 1;
+	if (vgaHWinit(PMINFO hw, m, p)) return 1;
 
 	/* set SYNC */
 	hw->MiscOutReg = 0xCB;
@@ -3135,10 +3457,10 @@
 
 	/* set interleaving */
 	hw->MXoptionReg &= ~0x00001000;
-	if (isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
+	if ((p->type != FB_TYPE_TEXT) && isInterleave(MINFO)) hw->MXoptionReg |= 0x00001000;
 
 	/* set DAC */
-	Ti3026_setpclk(PMINFO hw, m->pixclock, ACCESS_FBINFO(curr.final_bppShift));
+	Ti3026_setpclk(PMINFO hw, m->pixclock, p);
 	return 0;
 }
 #endif	/* CONFIG_FB_MATROX_MILLENIUM */
@@ -3148,6 +3470,10 @@
 	DBG("matroxfb_get_cmap_len")
 
 	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_VGATEXT
+		case 0:
+			return 16;	/* pseudocolor... 16 entries HW palette */
+#endif
 #ifdef FBCON_HAS_CFB4
 		case 4:
 			return 16;	/* pseudocolor... 16 entries HW palette */
@@ -3175,16 +3501,17 @@
 	return 16;	/* return something reasonable... or panic()? */
 }
 
-static int matroxfb_decode_var(CPMINFO struct fb_var_screeninfo *var, int *visual, int *video_cmap_len) {
+static int matroxfb_decode_var(CPMINFO struct display* p, struct fb_var_screeninfo *var, int *visual, int *video_cmap_len, unsigned int* ydstorg) {
 	unsigned int vramlen;
 	unsigned int memlen;
 
 	DBG("matroxfb_decode_var")
 	
-	if ((var->xres > var->xres_virtual) || (var->yres > var->yres_virtual) || 
-	    (var->xoffset > var->xres_virtual) || (var->yoffset > var->yres_virtual))
-		return -EINVAL;
 	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_VGATEXT
+		case 0:	 if (!ACCESS_FBINFO(capable.text)) return -EINVAL;
+			 break;
+#endif
 #ifdef FBCON_HAS_CFB4
 		case 4:	 if (!ACCESS_FBINFO(capable.cfb4)) return -EINVAL;
 			 break;
@@ -3203,40 +3530,74 @@
 #endif
 		default: return -EINVAL;
 	}
+	*ydstorg = 0;
 	vramlen = ACCESS_FBINFO(video.len_usable);
-	var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
-	memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
-	if (memlen > vramlen) 
-		return -EINVAL;	/* out of memory */
-	/* There is hardware bug that no line can cross 4MB boundary */
-	/* give up for CFB24, it is impossible to easy workaround it */
-	/* for other try to do something */
-	if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000) && (var->bits_per_pixel != 24)) {
-		int new_xres = var->xres_virtual;
-
-		if (new_xres <= 512)
-			new_xres = 512;
-		else if (new_xres <= 1024)
-			new_xres = 1024;
-		else if (new_xres <= 2048)
-			new_xres = 2048;
-		else
-			new_xres = var->xres_virtual;
-		memlen = new_xres * var->bits_per_pixel / 8;
-		/* if now out of memory, try shrink virtual height */
-		/* but if new virtual height is smaller than visible height, return -EINVAL */
-		if (var->yres_virtual * memlen > vramlen) {
-			unsigned int new_yres;
-
-			new_yres = vramlen / memlen;
-			if (new_yres < var->yres)
-				return -EINVAL;
-			var->yres_virtual = new_yres;
+	if (var->bits_per_pixel) {
+		var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel);
+		memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+		if (memlen > vramlen) {
+			var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel);
+			memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8;
+		}
+		/* There is hardware bug that no line can cross 4MB boundary */
+		/* give up for CFB24, it is impossible to easy workaround it */
+		/* for other try to do something */
+		if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) {
+			if (var->bits_per_pixel == 24) {
+				/* sorry */
+			} else {
+				unsigned int linelen;
+				unsigned int m1 = linelen = var->xres_virtual * var->bits_per_pixel / 8;
+				unsigned int m2 = PAGE_SIZE;	/* or 128 if you do not need PAGE ALIGNED address */
+				unsigned int max_yres;
+
+				while (m1) {
+					int t;
+
+					while (m2 >= m1) m2 -= m1;
+					t = m1;
+					m1 = m2;
+					m2 = t;
+				}
+				m2 = linelen * PAGE_SIZE / m2;
+				*ydstorg = m2 = 0x400000 % m2;
+				max_yres = (vramlen - m2) / linelen;
+				if (var->yres_virtual > max_yres)
+					var->yres_virtual = max_yres;
+			}
 		}
-		var->xres_virtual = new_xres;
+	} else {
+		matrox_text_round(PMINFO var, p);
+#if 0
+/* we must limit pixclock by mclk... 
+   Millenium I:    66 MHz = 15000
+   Millenium II:   61 MHz = 16300
+   Millenium G200: 83 MHz = 12000 */
+		if (var->pixclock < 15000)
+			var->pixclock = 15000;	/* limit for "normal" gclk & mclk */
+#endif
 	}
 
-	if (var->bits_per_pixel == 4) {
+	if (var->yres_virtual < var->yres)
+		var->yres = var->yres_virtual;
+	if (var->xres_virtual < var->xres)
+		var->xres = var->xres_virtual;
+	if (var->xoffset + var->xres > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yoffset + var->yres > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	if (var->bits_per_pixel == 0) {
+		var->red.offset = 0;
+		var->red.length = 6;
+		var->green.offset = 0;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 6;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		*visual = MX_VISUAL_PSEUDOCOLOR;
+	} else if (var->bits_per_pixel == 4) {
 		var->red.offset = 0;
 		var->red.length = 8;
 		var->green.offset = 0;
@@ -3425,6 +3786,8 @@
 	ACCESS_FBINFO(features.pll.in_div_min)   = 2;
 	ACCESS_FBINFO(features.pll.in_div_max)   = 63;
 	ACCESS_FBINFO(features.pll.post_shift_max) = 3;
+	if (ACCESS_FBINFO(devflags.noinit))
+		return;
 	ti3026_setMCLK(PMINFO hw, 60000);
 }
 #endif
@@ -3458,7 +3821,7 @@
 	DBG("MGA1064_ramdac_init");
 
 	/* ACCESS_FBINFO(features.DAC1064.vco_freq_min) = 120000; */
-	ACCESS_FBINFO(features.pll.vco_freq_min) = 50000; 
+	ACCESS_FBINFO(features.pll.vco_freq_min) = 62000; 
 	ACCESS_FBINFO(features.pll.ref_freq)     = 14318;
 	ACCESS_FBINFO(features.pll.feed_div_min) = 100;
 	ACCESS_FBINFO(features.pll.feed_div_max) = 127;
@@ -3477,10 +3840,13 @@
 	DBG("MGA1064_preinit")
 
 	/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+	ACCESS_FBINFO(capable.text) = 1;
 	ACCESS_FBINFO(capable.vxres) = vxres_mystique;
 	ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
 	ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
 
+	if (ACCESS_FBINFO(devflags.noinit)) 
+		return 0;	/* do not modify settings */
 	hw->MXoptionReg &= 0xC0000100;
 	hw->MXoptionReg |= 0x00094E20;
 	if (ACCESS_FBINFO(devflags.novga))
@@ -3513,8 +3879,9 @@
 
 #ifdef CONFIG_FB_MATROX_G100
 /* BIOS environ */
-static int x7AF4 = 0;    /* flags */
-#if 0
+static int x7AF4 = 0x10;    /* flags, maybe 0x10 = SDRAM, 0x00 = SGRAM??? */
+			/* G100 wants 0x10, G200 SGRAM does not care... */
+#if 0 
 static int def50 = 0;	/* reg50, & 0x0F, & 0x3000 (only 0x0000, 0x1000, 0x2000 (0x3000 disallowed and treated as 0) */
 #endif
 
@@ -3525,7 +3892,8 @@
 
 	DBG("MGAG100_progPixClock")
 	
-	outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS);
+	outDAC1064(PMINFO M1064_XPIXCLKCTRL, inDAC1064(PMINFO M1064_XPIXCLKCTRL) | M1064_XPIXCLKCTRL_DIS |
+	           M1064_XPIXCLKCTRL_PLL_UP);
 	switch (flags & 3) {
 		case 0:		reg = M1064_XPIXPLLAM; break;
 		case 1:		reg = M1064_XPIXPLLBM; break;
@@ -3544,9 +3912,11 @@
 		default:	selClk |= 0x0C; break;
 	}
 	mga_outb(M_MISC_REG, selClk);
-	for (clk = 65536; clk; clk--)
+	for (clk = 500000; clk; clk--) {
 		if (inDAC1064(PMINFO M1064_XPIXPLLSTAT) & 0x40)
 			break;
+		udelay(10);
+	};
 	if (!clk)
 		printk(KERN_ERR "matroxfb: Pixel PLL%c not locked after usual time\n", (reg-M1064_XPIXPLLAM-2)/4 + 'A');
 	selClk = inDAC1064(PMINFO M1064_XPIXCLKCTRL) & ~M1064_XPIXCLKCTRL_SRC_MASK;
@@ -3572,20 +3942,23 @@
 	static const int vxres_g100[] = {  512,        640, 768,  800,  832,  960, 
                                           1024, 1152, 1280,      1600, 1664, 1920, 
                                           2048, 0};
+        u_int32_t reg50;
 #if 0
-	u_int32_t reg50;
 	u_int32_t q;
 #endif
 
 	DBG("MGAG100_preinit")
 	
 	/* ACCESS_FBINFO(capable.cfb4) = 0; ... preinitialized by 0 */
+	ACCESS_FBINFO(capable.text) = 1;
 	ACCESS_FBINFO(capable.vxres) = vxres_g100;
 	ACCESS_FBINFO(features.accel.has_cacheflush) = 1;
 	ACCESS_FBINFO(cursor.timer.function) = matroxfb_DAC1064_flashcursor;
-	
+
+	if (ACCESS_FBINFO(devflags.noinit))
+		return 0;
 	hw->MXoptionReg &= 0xC0000100;
-	hw->MXoptionReg |= 0x00078C20;
+	hw->MXoptionReg |= 0x00078020;
 	if (ACCESS_FBINFO(devflags.novga))
 		hw->MXoptionReg &= ~0x00000100;
 	if (ACCESS_FBINFO(devflags.nobios))
@@ -3593,36 +3966,49 @@
 	if (ACCESS_FBINFO(devflags.nopciretry))
 		hw->MXoptionReg |=  0x20000000;
 	pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
-
-	mga_outl(M_CTLWTST, 0x03258A31);	/* 03258A31 is x7AF0, default is 0x02032521 */
-#if 0
-	hw->MXoptionReg |= 0x1000;
-	pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
 	pci_read_config_dword(ACCESS_FBINFO(pcidev), 0x50, &reg50);
-	q = def50 & 0x3000;
-	reg50 = (reg50 & ~0x3000) | q;
+	reg50 &= ~0x3000;
 	pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
-	mga_outb(0x1C05, 0x00);
-	mga_outb(0x1C05, 0x80);
-	udelay(100);
-	mga_outb(0x1C05, 0x40);
-	mga_outb(0x1C05, 0xC0);
-	pci_write_config_byte(ACCESS_FBINFO(pcidev), 0x50, def50 & 0x0F);
-	{
+	if (!(x7AF4 & 0x10))
+		hw->MXoptionReg |= 0x4000;
+	if (ACCESS_FBINFO(devflags.accelerator) == FB_ACCEL_MATROX_MGAG100) {
+		hw->MXoptionReg |= 0x1080;
+		pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+		mga_outl(M_CTLWTST, 0x01032521);
+		/* mga_outl(M_CTLWTST, 0x03258A31); */ 
+		udelay(100);
+		mga_outb(0x1C05, 0x00);
+		mga_outb(0x1C05, 0x80);
+		udelay(100);
+		mga_outb(0x1C05, 0x40);
+		mga_outb(0x1C05, 0xC0);
+		udelay(100);
+		reg50 &= ~0xFF;
+		reg50 |=  0x07;
+		pci_write_config_dword(ACCESS_FBINFO(pcidev), 0x50, reg50);
+		/* it should help with G100 */
 		mga_outb(M_GRAPHICS_INDEX, 6);
 		mga_outb(M_GRAPHICS_DATA, (mga_inb(M_GRAPHICS_DATA) & 3) | 4);
 		mga_setr(M_EXTVGA_INDEX, 0x03, 0x81);
 		mga_setr(M_EXTVGA_INDEX, 0x04, 0x00);
-		mga_writeb(ACCESS_FBINFO(video.vbase), 0x000, 0xAA);
-		mga_writeb(ACCESS_FBINFO(video.vbase), 0x800, 0x55);
-		if (mga_readb(ACCESS_FBINFO(video.vbase), 0x000) != 0xAA) {
+		mga_writeb(ACCESS_FBINFO(video.vbase), 0x0000, 0xAA);
+		mga_writeb(ACCESS_FBINFO(video.vbase), 0x0800, 0x55);
+		mga_writeb(ACCESS_FBINFO(video.vbase), 0x4000, 0x55);
+		if (mga_readb(ACCESS_FBINFO(video.vbase), 0x0000) != 0xAA) {
 			hw->MXoptionReg &= ~0x1000;
 		}
+	} else {
+		hw->MXoptionReg |= 0x00000C00;
+		mga_outl(M_CTLWTST, 0x042450A1);
+		mga_outb(0x1E47, 0x00);
+		mga_outb(0x1E46, 0x00);
+		udelay(10);
+		mga_outb(0x1C05, 0x00);
+		mga_outb(0x1C05, 0x80);
+		udelay(100);
+		mga_outw(0x1E44, 0x0108);
 	}
-#endif
 	hw->MXoptionReg = (hw->MXoptionReg & ~0x1F8000) | 0x78000;
-	if (!(x7AF4 & 0x10))
-		hw->MXoptionReg |= 0x4000;
 	pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
 	return 0;
 }
@@ -3631,8 +4017,9 @@
 	u_int8_t b;
 
 	DBG("MGAG100_reset")
-	
-	ACCESS_FBINFO(features.pll.vco_freq_min) = 50000;
+
+	/* there are some instabilities if in_div > 19 && vco < 61000 */
+	ACCESS_FBINFO(features.pll.vco_freq_min) = 62000;
 	ACCESS_FBINFO(features.pll.ref_freq)     = 27000;
 	ACCESS_FBINFO(features.pll.feed_div_min) = 7;
 	ACCESS_FBINFO(features.pll.feed_div_max) = 127;
@@ -3658,13 +4045,17 @@
 			pci_write_config_byte(ibm, PCI_IO_LIMIT, 0x00);	/* ??? */
 		}
 #endif
-		if (x7AF4 & 8) {
-			hw->MXoptionReg |= 0x40;
-			pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+		if (!ACCESS_FBINFO(devflags.noinit)) {
+			if (x7AF4 & 8) {
+				hw->MXoptionReg |= 0x40;
+				pci_write_config_dword(ACCESS_FBINFO(pcidev), PCI_OPTION_REG, hw->MXoptionReg);
+			}
+			mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
 		}
-		mga_setr(M_EXTVGA_INDEX, 0x06, 0x50);
 	}
-	DAC1064_setmclk(PMINFO hw, DAC1064_OPT_SCLK_PLL, 120000);
+	DAC1064_setmclk(PMINFO hw, DAC1064_OPT_RESERVED | DAC1064_OPT_MDIV2 | DAC1064_OPT_GDIV1 | DAC1064_OPT_SCLK_PLL, 133333);
+	if (ACCESS_FBINFO(devflags.noinit))
+		return;
 	MGAG100_setPixClock(PMINFO 4, 25175);
 	MGAG100_setPixClock(PMINFO 5, 28322);
 	if (x7AF4 & 0x10) {
@@ -3726,6 +4117,7 @@
 			    unsigned blue, unsigned transp,
 			    struct fb_info *fb_info)
 {
+	struct display* p;
 #ifdef CONFIG_FB_MATROX_MULTIHEAD
 	struct matrox_fb_info* minfo = (struct matrox_fb_info*)fb_info;
 #endif
@@ -3747,18 +4139,22 @@
 	ACCESS_FBINFO(palette[regno].blue)  = blue;
 	ACCESS_FBINFO(palette[regno].transp) = transp;
 
-	if (ACCESS_FBINFO(curr.var.grayscale)) {
+	p = ACCESS_FBINFO(currcon_display);
+	if (p->var.grayscale) {
 		/* gray = 0.30*R + 0.59*G + 0.11*B */
 		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
 	}
 
-	red = CNVT_TOHW(red, ACCESS_FBINFO(curr.var.red.length));
-	green = CNVT_TOHW(green, ACCESS_FBINFO(curr.var.green.length));
-	blue = CNVT_TOHW(blue, ACCESS_FBINFO(curr.var.blue.length));
-	transp = CNVT_TOHW(transp, ACCESS_FBINFO(curr.var.transp.length));
+	red = CNVT_TOHW(red, p->var.red.length);
+	green = CNVT_TOHW(green, p->var.green.length);
+	blue = CNVT_TOHW(blue, p->var.blue.length);
+	transp = CNVT_TOHW(transp, p->var.transp.length);
 
-	switch (ACCESS_FBINFO(curr.var.bits_per_pixel)) {
-#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4)
+	switch (p->var.bits_per_pixel) {
+#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_VGATEXT)
+#ifdef FBCON_HAS_VGATEXT
+	case 0:
+#endif
 #ifdef FBCON_HAS_CFB4
 	case 4:
 #endif
@@ -3774,45 +4170,37 @@
 #ifdef FBCON_HAS_CFB16	
 	case 16:
 		ACCESS_FBINFO(cmap.cfb16[regno]) =
-			(red << ACCESS_FBINFO(curr.var.red.offset))     | 
-			(green << ACCESS_FBINFO(curr.var.green.offset)) | 
-			(blue << ACCESS_FBINFO(curr.var.blue.offset))   |
-			(transp << ACCESS_FBINFO(curr.var.transp.offset)); /* for 1:5:5:5 */
+			(red << p->var.red.offset)     | 
+			(green << p->var.green.offset) | 
+			(blue << p->var.blue.offset)   |
+			(transp << p->var.transp.offset); /* for 1:5:5:5 */
 		break;
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 24:
 		ACCESS_FBINFO(cmap.cfb24[regno]) =
-			(red   << ACCESS_FBINFO(curr.var.red.offset))   |
-			(green << ACCESS_FBINFO(curr.var.green.offset)) |
-			(blue  << ACCESS_FBINFO(curr.var.blue.offset));
+			(red   << p->var.red.offset)   |
+			(green << p->var.green.offset) |
+			(blue  << p->var.blue.offset);
 		break;
 #endif
 #ifdef FBCON_HAS_CFB32
 	case 32:
 		ACCESS_FBINFO(cmap.cfb32[regno]) =
-			(red   << ACCESS_FBINFO(curr.var.red.offset))   |
-			(green << ACCESS_FBINFO(curr.var.green.offset)) |
-			(blue  << ACCESS_FBINFO(curr.var.blue.offset))  |
-			(transp << ACCESS_FBINFO(curr.var.transp.offset));	/* 8:8:8:8 */
+			(red   << p->var.red.offset)   |
+			(green << p->var.green.offset) |
+			(blue  << p->var.blue.offset)  |
+			(transp << p->var.transp.offset);	/* 8:8:8:8 */
 		break;
 #endif
 	}
 	return 0;
 }
 
-static void do_install_cmap(WPMINFO int con)
+static void do_install_cmap(WPMINFO struct display* dsp)
 {
-	struct display* dsp;
-
 	DBG("do_install_cmap")
 
-	if (con != ACCESS_FBINFO(currcon))
-		return;
-	if (con >= 0)
-		dsp = fb_display+con;
-	else
-		dsp = ACCESS_FBINFO(fbcon.disp);
 	if (dsp->cmap.len)
 		fb_set_cmap(&dsp->cmap, 1, matrox_setcolreg, &ACCESS_FBINFO(fbcon));
 	else
@@ -3903,7 +4291,7 @@
 		outTi3026(PMINFO TVP3026_XPLLADDR, 0x00);
 		for (i = 3; i < 6; i++)
 			outTi3026(PMINFO TVP3026_XLOOPPLLDATA, hw->DACclk[i]);
-		if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[3] & 0xC0) == 0xC0)) {
+		if ((hw->MiscOutReg & 0x08) && ((hw->DACclk[5] & 0x80) == 0x80)) {
 			int tmout;
 
 			outTi3026(PMINFO TVP3026_XPLLADDR, 0x3F);
@@ -3919,8 +4307,14 @@
 		}
 	}
 	if (p && p->conp) {
-		matroxfb_ti3026_createcursor(PMINFO p);
-		i = matroxfb_fastfont_tryset(PMINFO p);
+		if (p->type == FB_TYPE_TEXT) {
+			matrox_text_createcursor(PMINFO p);
+			matrox_text_loadfont(PMINFO p);
+			i = 0;
+		} else {
+			matroxfb_ti3026_createcursor(PMINFO p);
+			i = matroxfb_fastfont_tryset(PMINFO p);
+		}
 	} else
 		i = 0;
 	if (i) {
@@ -3946,21 +4340,28 @@
 static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con,
 			 struct fb_info *info)
 {
-
+	struct display* p;
 	DBG("matroxfb_get_fix")
 
 #define minfo ((struct matrox_fb_info*)info)
+
+	if (con >= 0)
+		p = fb_display + con;
+	else
+		p = ACCESS_FBINFO(fbcon.disp);
+
 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 	strcpy(fix->id,"MATROX");
 
-	fix->smem_start = (void*)ACCESS_FBINFO(video.base);
-	fix->smem_len = ACCESS_FBINFO(video.len);
-	fix->type = ACCESS_FBINFO(curr.video_type);
-	fix->visual = ACCESS_FBINFO(curr.visual);
+	fix->smem_start = (void*)ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes);
+	fix->smem_len = ACCESS_FBINFO(video.len) - ACCESS_FBINFO(curr.ydstorg.bytes);
+	fix->type = p->type;
+	fix->type_aux = p->type_aux;
+	fix->visual = p->visual;
 	fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */
 	fix->ypanstep = 1;
 	fix->ywrapstep = 0;
-	fix->line_length = (ACCESS_FBINFO(curr.var.xres_virtual) * ACCESS_FBINFO(curr.var.bits_per_pixel)) >> 3;
+	fix->line_length = p->line_length;
 	fix->mmio_start = (void*)ACCESS_FBINFO(mmio.base);
 	fix->mmio_len = ACCESS_FBINFO(mmio.len);
 	fix->accel = ACCESS_FBINFO(devflags.accelerator);
@@ -3971,14 +4372,15 @@
 static int matroxfb_get_var(struct fb_var_screeninfo *var, int con,
 			 struct fb_info *info)
 {
-
+#define minfo ((struct matrox_fb_info*)info)
 	DBG("matroxfb_get_var")
 	
 	if(con < 0)
-		*var=ACCESS_FBINFO2(info, curr.var);
+		*var=ACCESS_FBINFO(fbcon.disp)->var;
 	else
 		*var=fb_display[con].var;
 	return 0;
+#undef minfo
 }
 
 static int matroxfb_set_var(struct fb_var_screeninfo *var, int con,
@@ -3988,12 +4390,17 @@
 	int err;
 	int visual;
 	int cmap_len;
+	unsigned int ydstorg;
 	struct display* display;
 	int chgvar;
 
 	DBG("matroxfb_set_var")
 
-	if ((err = matroxfb_decode_var(PMINFO var, &visual, &cmap_len)) != 0) 
+	if (con >= 0)
+		display = fb_display + con;
+	else
+		display = ACCESS_FBINFO(fbcon.disp);
+	if ((err = matroxfb_decode_var(PMINFO display, var, &visual, &cmap_len, &ydstorg)) != 0) 
 		return err;
 	switch (var->activate & FB_ACTIVATE_MASK) {
 		case FB_ACTIVATE_TEST:	return 0;
@@ -4002,7 +4409,6 @@
 		default:		return -EINVAL; /* unknown */
 	}
 	if (con >= 0) {
-		display = fb_display+con;
 		chgvar = ((display->var.xres != var->xres) || 
 		    (display->var.yres != var->yres) || 
                     (display->var.xres_virtual != var->xres_virtual) ||
@@ -4012,18 +4418,23 @@
 		    memcmp(&display->var.green, &var->green, sizeof(var->green)) ||
 		    memcmp(&display->var.blue, &var->blue, sizeof(var->blue)));
 	} else {
-		display = ACCESS_FBINFO(fbcon.disp);
 		chgvar = 0;
 	}
 	display->var = *var;
 	/* cmap */
-	display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase));
+	display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg;
 	display->visual = visual;
-	display->type = FB_TYPE_PACKED_PIXELS;
-	display->type_aux = 0;
 	display->ypanstep = 1;
 	display->ywrapstep = 0;
-	display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+	if (var->bits_per_pixel) {
+		display->type = FB_TYPE_PACKED_PIXELS;
+		display->type_aux = 0;
+		display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3;
+	} else {
+		display->type = FB_TYPE_TEXT;
+		display->type_aux = ACCESS_FBINFO(devflags.text_type_aux);
+		display->next_line = display->line_length = (var->xres_virtual / (fontwidth(display)?fontwidth(display):8)) * ACCESS_FBINFO(devflags.textstep);
+	}
 	display->can_soft_blank = 1;
 	display->inverse = ACCESS_FBINFO(devflags.inverse);
 	/* conp, fb_info, vrows, cursor_x, cursor_y, fgcol, bgcol */
@@ -4036,9 +4447,21 @@
 	if (con == ACCESS_FBINFO(currcon)) {
 		unsigned int pos;
 
-		ACCESS_FBINFO(curr.var) = *var;
-		ACCESS_FBINFO(curr.visual) = visual;
 		ACCESS_FBINFO(curr.cmap_len) = cmap_len;
+		if (display->type == FB_TYPE_TEXT) {
+			/* textmode must be in first megabyte, so no ydstorg allowed */
+			ACCESS_FBINFO(curr.ydstorg.bytes) = 0;
+			ACCESS_FBINFO(curr.ydstorg.chunks) = 0;
+			ACCESS_FBINFO(curr.ydstorg.pixels) = 0;
+		} else {
+			ydstorg += ACCESS_FBINFO(devflags.ydstorg);
+			ACCESS_FBINFO(curr.ydstorg.bytes) = ydstorg;
+			ACCESS_FBINFO(curr.ydstorg.chunks) = ydstorg >> (isInterleave(MINFO)?3:2);
+			if (var->bits_per_pixel == 4)
+				ACCESS_FBINFO(curr.ydstorg.pixels) = ydstorg;
+			else
+				ACCESS_FBINFO(curr.ydstorg.pixels) = (ydstorg * 8) / var->bits_per_pixel;
+		}
 		ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel);
 		if (visual == MX_VISUAL_PSEUDOCOLOR) {
 			int i;
@@ -4070,24 +4493,27 @@
 			del_timer(&ACCESS_FBINFO(cursor.timer));
 			ACCESS_FBINFO(cursor.state) = CM_ERASE;
 
-			ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt));
-			pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
-			if (mga_ydstorg(MINFO)) {
-				if (isInterleave(MINFO))
-					pos += mga_ydstorg(MINFO) >> 3;
+			ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt, display));
+			if (display->type == FB_TYPE_TEXT) {
+				if (fontheight(display))
+					pos = var->yoffset / fontheight(display) * display->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(display)?fontwidth(display):8);
 				else
-					pos += mga_ydstorg(MINFO) >> 2;
+					pos = 0;
+			} else {
+				pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32;
+				pos += ACCESS_FBINFO(curr.ydstorg.chunks);
 			}
 
 			hw->CRTC[0x0D] = pos & 0xFF;
 			hw->CRTC[0x0C] = (pos & 0xFF00) >> 8;
 			hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F);
 			ACCESS_FBINFO(hw_switch->restore(PMINFO hw, ohw, display));
+			ACCESS_FBINFO(cursor.redraw) = 1;
 			ACCESS_FBINFO(currenthw) = hw;
 			ACCESS_FBINFO(newhw) = ohw;
-			matrox_cfbX_init(MINFO);
-			do_install_cmap(PMINFO con);
-#if defined(CONFIG_FB_COMPAT_XPMAC)
+			matrox_cfbX_init(PMINFO display);
+			do_install_cmap(PMINFO display);
+#if defined(CONFIG_PPC) && defined(CONFIG_FB_COMPAT_XPMAC)
 			if (console_fb_info == &ACCESS_FBINFO(fbcon)) {
 				int vmode, cmode;
 
@@ -4095,19 +4521,17 @@
 				display_info.height = var->yres;
 				display_info.depth = var->bits_per_pixel;
 				display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8;
-				if (mac_var_to_vmode(var, &vmode, &cmode)
+				if (mac_var_to_vmode(var, &vmode, &cmode))
 					display_info.mode = 0;
 				else
 					display_info.mode = vmode;
 				strcpy(display_info.name, ACCESS_FBINFO(matrox_name));
 				display_info.fb_address = ACCESS_FBINFO(video.base);
-				/* we should not expose this addresses outside of driver. Every access to DAC must be
-                                   exclusive locked by spinlock_irq(ACCESS_FBINFO(lock.DAC)) or by turning hardware cursor (flashing) OFF */
-				display_info.cmap_adr_address = ACCESS_FBINFO(mmio.base) + M_DAC_REG;
-				display_info.cmap_data_address = ACCESS_FBINFO(mmio.base) + M_DAC_VAL;
+				display_info.cmap_adr_address = 0;
+				display_info.cmap_data_address = 0;
 				display_info.disp_reg_address = ACCESS_FBINFO(mmio.base);
 			}
-#endif /* CONFIG_FB_COMPAT_XPMAC */
+#endif /* CONFIG_PPC && CONFIG_FB_COMPAT_XPMAC */
 		}
 	}
 	return 0;
@@ -4141,11 +4565,13 @@
 static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
 			     struct fb_info *info)
 {
-	struct display* dsp = (con < 0) ? info->disp : fb_display+con;
+#define minfo ((struct matrox_fb_info*)info)
+	struct display* dsp = (con < 0) ? ACCESS_FBINFO(fbcon.disp) 
+					: fb_display + con;
 
 	DBG("matroxfb_get_cmap")
 
-	if (con == ACCESS_FBINFO2(info, currcon)) /* current console? */
+	if (con == ACCESS_FBINFO(currcon)) /* current console? */
 		return fb_get_cmap(cmap, kspc, matrox_getcolreg, info);
 	else if (dsp->cmap.len) /* non default colormap? */
 		fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
@@ -4153,6 +4579,7 @@
 		fb_copy_cmap(fb_default_cmap(matroxfb_get_cmap_len(&dsp->var)),
 			     cmap, kspc ? 0 : 2);
 	return 0;
+#undef minfo
 }
 
 static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
@@ -4160,6 +4587,7 @@
 {
 	unsigned int cmap_len;
 	struct display* dsp = (con < 0) ? info->disp : (fb_display + con);
+#define minfo ((struct matrox_fb_info*)info)
 
 	DBG("matroxfb_set_cmap")
 
@@ -4171,11 +4599,12 @@
 		if (err)
 			return err;
 	}
-	if (con == ACCESS_FBINFO2(info, currcon))			/* current console? */
+	if (con == ACCESS_FBINFO(currcon)) {			/* current console? */
 		return fb_set_cmap(cmap, kspc, matrox_setcolreg, info);
-	else
+	} else
 		fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
 	return 0;
+#undef minfo	
 }
 
 static int matroxfb_ioctl(struct inode *inode, struct file *file, 
@@ -4210,8 +4639,8 @@
 
 	if (ACCESS_FBINFO(currcon) >= 0) {
 		/* Do we have to save the colormap? */
-		cmap = &fb_display[ACCESS_FBINFO2(info, currcon)].cmap;
-		dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO2(info, currcon), cmap->len);
+		cmap = &(ACCESS_FBINFO(currcon_display)->cmap);
+		dprintk(KERN_DEBUG "switch1: con = %d, cmap.len = %d\n", ACCESS_FBINFO(currcon), cmap->len);
 
 		if (cmap->len) {
 			dprintk(KERN_DEBUG "switch1a: %p %p %p %p\n", cmap->red, cmap->green, cmap->blue, cmap->transp);
@@ -4224,7 +4653,7 @@
 		}
 	}
 	ACCESS_FBINFO(currcon) = con;
-	ACCESS_FBINFO(currcon_display) = fb_display+con;
+	ACCESS_FBINFO(currcon_display) = fb_display + con;
 	fb_display[con].var.activate = FB_ACTIVATE_NOW;
 #ifdef DEBUG
 	cmap = &fb_display[con].cmap;
@@ -4281,7 +4710,11 @@
 #define RS960x720	8
 #define RS1152x864	9
 #define RS1408x1056	10
-/* B-F */
+#define RS640x350	11
+#define RS1056x344	12	/* 132 x 43 text */
+#define RS1056x400	13	/* 132 x 50 text */
+#define RS1056x480	14	/* 132 x 60 text */
+/* 0F-FF */
 static struct { int xres, yres, left, right, upper, lower, hslen, vslen, vfreq; } timmings[] __initdata = {
 	{  640,  400,  48, 16, 39,  8,  96, 2, 70 },
 	{  640,  480,  48, 16, 33, 10,  96, 2, 60 },
@@ -4292,27 +4725,35 @@
 	{  768,  576, 144, 16, 28,  6, 112, 4, 60 },
 	{  960,  720, 144, 24, 28,  8, 112, 4, 60 },
 	{ 1152,  864, 192, 32, 30,  4, 128, 4, 60 },
-	{ 1408, 1056, 256, 40, 32,  5, 144, 5, 60 }
+	{ 1408, 1056, 256, 40, 32,  5, 144, 5, 60 },
+	{  640,  350,  48, 16, 39,  8,  96, 2, 70 },
+	{ 1056,  344,  96, 24, 59, 44, 160, 2, 70 },
+	{ 1056,  400,  96, 24, 39,  8, 160, 2, 70 },
+	{ 1056,  480,  96, 24, 36, 12, 160, 3, 60 }
 };
 
-#define RSDepth(X)	(((X) >> 4) & 0x0F)
+#define RSDepth(X)	(((X) >> 8) & 0x0F)
 #define RS8bpp		0x1
 #define RS15bpp		0x2
 #define RS16bpp		0x3
 #define RS32bpp		0x4
 #define RS4bpp		0x5
 #define RS24bpp		0x6
-/* 7-F */
+#define RSText		0x7
+#define RSText8		0x8
+/* 9-F */
 static struct { struct fb_bitfield red, green, blue, transp; int bits_per_pixel; } colors[] __initdata = {
 	{ {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  8 },
 	{ { 10, 5, 0}, { 5, 5, 0}, { 0, 5, 0}, { 15, 1, 0}, 16 },
 	{ { 11, 5, 0}, { 6, 5, 0}, { 0, 5, 0}, {  0, 0, 0}, 16 },
 	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, { 24, 8, 0}, 32 },
 	{ {  0, 8, 0}, { 0, 8, 0}, { 0, 8, 0}, {  0, 0, 0},  4 },
-	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {  0, 0, 0}, 24 }
+	{ { 16, 8, 0}, { 8, 8, 0}, { 0, 8, 0}, {  0, 0, 0}, 24 },
+	{ {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 },	/* textmode with (default) VGA8x16 */
+	{ {  0, 6, 0}, { 0, 6, 0}, { 0, 6, 0}, {  0, 0, 0},  0 }	/* textmode hardwired to VGA8x8 */
 };
 
-#define RSCreate(X,Y)	((X) | ((Y) << 4))
+#define RSCreate(X,Y)	((X) | ((Y) << 8))
 static struct { unsigned int vesa; unsigned int info; } *RSptr, vesamap[] __initdata = {
 /* default must be first */
 #ifdef FBCON_HAS_CFB8
@@ -4328,8 +4769,11 @@
 	{ 0x11C, RSCreate(RS1600x1200, RS8bpp ) },
 #endif
 #ifdef FBCON_HAS_CFB4
+	{ 0x010, RSCreate(RS640x350,   RS4bpp ) },
+	{ 0x012, RSCreate(RS640x480,   RS4bpp ) },
 	{ 0x102, RSCreate(RS800x600,   RS4bpp ) },
 	{ 0x104, RSCreate(RS1024x768,  RS4bpp ) },
+	{ 0x106, RSCreate(RS1280x1024, RS4bpp ) },
 #endif
 #ifdef FBCON_HAS_CFB16
 	{ 0x110, RSCreate(RS640x480,   RS15bpp) },
@@ -4371,6 +4815,18 @@
 	{ 0x193, RSCreate(RS1152x864,  RS32bpp) },
 	{ 0x11B, RSCreate(RS1280x1024, RS32bpp) },
 	{ 0x19B, RSCreate(RS1408x1056, RS32bpp) },
+	{ 0x11F, RSCreate(RS1600x1200, RS32bpp) },
+#endif
+#ifdef FBCON_HAS_VGATEXT
+	{ 0x002, RSCreate(RS640x400,   RSText)  },	/* 80x25 */
+	{ 0x003, RSCreate(RS640x400,   RSText)  },	/* 80x25 */
+	{ 0x007, RSCreate(RS640x400,   RSText)  },	/* 80x25 */
+	{ 0x1C0, RSCreate(RS640x400,   RSText8) },	/* 80x50 */
+	{ 0x108, RSCreate(RS640x480,   RSText8) },	/* 80x60 */
+	{ 0x109, RSCreate(RS1056x400,  RSText)  },	/* 132x25 */
+	{ 0x10A, RSCreate(RS1056x344,  RSText8) },	/* 132x43 */
+	{ 0x10B, RSCreate(RS1056x400,  RSText8) },	/* 132x50 */
+	{ 0x10C, RSCreate(RS1056x480,  RSText8) },	/* 132x60 */
 #endif
 	{     0, 0                                 }};
 
@@ -4385,6 +4841,7 @@
 static int no_pci_retry = 0;		/* "matrox:nopciretry" */
 static int novga = 0;			/* "matrox:novga" */
 static int nobios = 0;			/* "matrox:nobios" */
+static int noinit = 0;			/* "matrox:noinit" */
 static int inverse = 0;			/* "matrox:inverse" */
 static int hwcursor = 1;		/* "matrox:nohwcursor" */
 static int blink = 1;			/* "matrox:noblink" */
@@ -4392,7 +4849,7 @@
 static unsigned int fastfont = 0;	/* "matrox:fastfont:xxxxx" */
 static int dev = -1;			/* "matrox:dev:xxxxx" */
 static unsigned int vesa = 0x101;	/* "matrox:vesa:xxxxx" */
-static unsigned int depth = 0;		/* "matrox:depth:xxxxx" */
+static int depth = -1;			/* "matrox:depth:xxxxx" */
 static unsigned int xres = 0;		/* "matrox:xres:xxxxx" */
 static unsigned int yres = 0;		/* "matrox:yres:xxxxx" */
 static unsigned int upper = 0;		/* "matrox:upper:xxxxx" */
@@ -4428,6 +4885,7 @@
 			dev = simple_strtoul(this_opt+4, NULL, 0);
 		else if (!strncmp(this_opt, "depth:", 6)) {
 			switch (simple_strtoul(this_opt+6, NULL, 0)) {
+				case 0: depth = RSText; break;
 				case 4: depth = RS4bpp; break;
 				case 8: depth = RS8bpp; break;
 				case 15:depth = RS15bpp; break;
@@ -4496,6 +4954,8 @@
 				novga = !value;
 			else if (!strcmp(this_opt, "bios"))
 				nobios = !value;
+			else if (!strcmp(this_opt, "init"))
+				noinit = !value;
 			else if (!strcmp(this_opt, "inv24"))
 				inv24 = value;
 			else if (!strcmp(this_opt, "cross4MB"))
@@ -4533,7 +4993,7 @@
 	/* at least 2MB */
 	if (maxSize < 0x0200000) return 0;
 	if (maxSize > 0x1000000) maxSize = 0x1000000;
-	
+
 	mga_outb(M_EXTVGA_INDEX, 0x03);
 	mga_outb(M_EXTVGA_DATA, mga_inb(M_EXTVGA_DATA) | 0x80);
 
@@ -4600,9 +5060,12 @@
 	ACCESS_FBINFO(millenium) = 1;
 	ACCESS_FBINFO(milleniumII) = (ACCESS_FBINFO(pcidev)->device != PCI_DEVICE_ID_MATROX_MIL);
 	ACCESS_FBINFO(capable.cfb4) = 1;
+	ACCESS_FBINFO(capable.text) = 1; /* isMilleniumII(MINFO); */
 	ACCESS_FBINFO(capable.vxres) = isMilleniumII(MINFO)?vxres_mill2:vxres_mill1;
 	ACCESS_FBINFO(cursor.timer.function) = matroxfb_ti3026_flashcursor;
 
+	if (ACCESS_FBINFO(devflags.noinit))
+		return 0;
 	/* preserve VGA I/O, BIOS and PPC */
 	hw->MXoptionReg &= 0xC0000100;
 	hw->MXoptionReg |= 0x002C0000;
@@ -4688,6 +5151,7 @@
 #define DEVF_MILLENIUM	0x04
 #define	DEVF_MILLENIUM2	0x08
 #define DEVF_CROSS4MB	0x10
+#define DEVF_TEXT4B	0x20
 static struct board {
 	unsigned short vendor, device, rev, svid, sid;
 	unsigned int flags;
@@ -4698,8 +5162,8 @@
 #ifdef CONFIG_FB_MATROX_MILLENIUM
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL,	0xFF,
 		0,			0,
-		DEVF_MILLENIUM,
-		220000,
+		DEVF_MILLENIUM | DEVF_TEXT4B,
+		230000,
 		&vbMillenium,
 		"Millennium (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2,	0xFF,
@@ -4733,45 +5197,51 @@
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MGA_G100_PCI,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"MGA-G100 (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100,	0xFF,
 		0,			0,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"unknown G100 (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_GENERIC,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"MGA-G100 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MGA_G100_AGP,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"MGA-G100 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,	PCI_SS_ID_SIEMENS_MGA_G100_AGP,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"MGA-G100 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_PRODUCTIVA_G100_AGP,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"Productiva G100 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G100_AGP,	0xFF,
 		0,			0,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG100,
 		"unknown G100 (AGP)"},
+	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_PCI,	0xFF,
+		0,			0,
+		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
+		250000,
+		&vbG200,
+		"unknown G200 (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_GENERIC,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
@@ -4781,7 +5251,7 @@
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MYSTIQUE_G200_AGP,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG200,
 		"Mystique G200 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
@@ -4793,19 +5263,19 @@
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_MATROX,	PCI_SS_ID_MATROX_MARVEL_G200_AGP,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG200,
 		"Marvel G200 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
 		PCI_SS_VENDOR_ID_SIEMENS_NIXDORF,	PCI_SS_ID_SIEMENS_MGA_G200_AGP,
 		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
-		220000,
+		230000,
 		&vbG200,
 		"MGA-G200 (AGP)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_G200_AGP,	0xFF,
 		0,			0,
 		DEVF_VIDEO64BIT | DEVF_SWAPS,
-		220000,
+		230000,
 		&vbG200,
 		"unknown G200 (AGP)"},
 #endif
@@ -4833,6 +5303,20 @@
 
 	printk(KERN_INFO "matroxfb: Matrox %s detected\n", b->name);
 	ACCESS_FBINFO(devflags.video64bits) = b->flags & DEVF_VIDEO64BIT;
+	if (b->flags & DEVF_TEXT4B) {
+		ACCESS_FBINFO(devflags.vgastep) = 4;
+		ACCESS_FBINFO(devflags.textmode) = 4;
+		ACCESS_FBINFO(devflags.vgastepdisp) = 16;
+		ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP16;
+	} else {
+		ACCESS_FBINFO(devflags.vgastep) = 8;
+		ACCESS_FBINFO(devflags.textmode) = 1;
+		ACCESS_FBINFO(devflags.vgastepdisp) = 64;
+		ACCESS_FBINFO(devflags.text_type_aux) = FB_AUX_TEXT_MGA_STEP8;
+	}
+	ACCESS_FBINFO(devflags.textstep) = ACCESS_FBINFO(devflags.vgastep) * ACCESS_FBINFO(devflags.textmode);
+	ACCESS_FBINFO(devflags.textvram) = 65536 / ACCESS_FBINFO(devflags.textmode);
+
 	if (ACCESS_FBINFO(capable.cross4MB) < 0)
 		ACCESS_FBINFO(capable.cross4MB) = b->flags & DEVF_CROSS4MB;
 	if (b->flags & DEVF_SWAPS) {
@@ -4886,8 +5370,12 @@
 			dprintk(KERN_WARNING "matroxfb: PCI BIOS did not enable device!\n");
 			cmd = (cmd | PCI_COMMAND_MEMORY) & ~PCI_COMMAND_VGA_PALETTE;
 			mga_option &=  0xBFFFFEFF; 
+			/* we must not enable VGA, BIOS if PCI BIOS did not enable device itself */
 			ACCESS_FBINFO(devflags.novga) = 1;
 			ACCESS_FBINFO(devflags.nobios) = 1;
+			/* we must initialize device if PCI BIOS did not enable it.
+			   It probably means that it is second head ... */
+			ACCESS_FBINFO(devflags.noinit) = 0;
 		}
 		mga_option |= MX_OPTION_BSWAP;
 		if (pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437, NULL)) {
@@ -4931,13 +5419,16 @@
 			ACCESS_FBINFO(video.len) = end - offs;
 		}
 #endif
-		mga_ydstorg(MINFO) = offs;
+		ACCESS_FBINFO(devflags.ydstorg) = offs;
 		video_base_phys += offs;
+		if (offs)
+			ACCESS_FBINFO(capable.text) = 0;
+#else
+		ACCESS_FBINFO(devflags.ydstorg) = 0;
 #endif
 	}
-	ACCESS_FBINFO(curr.video_type) = FB_TYPE_PACKED_PIXELS;
 	ACCESS_FBINFO(currcon) = -1;
-	ACCESS_FBINFO(currcon_display) = NULL;
+	ACCESS_FBINFO(currcon_display) = d;
 	mga_iounmap(ACCESS_FBINFO(video.vbase));
 	ACCESS_FBINFO(video.base) = video_base_phys;
 	if (mga_ioremap(video_base_phys, ACCESS_FBINFO(video.len), MGA_IOREMAP_FB, &ACCESS_FBINFO(video.vbase))) {
@@ -4995,12 +5486,14 @@
 			vslen = timmings[res].vslen;
 		if (!(fv||fh||maxclk||pixclock))
 			fv = timmings[res].vfreq;
-		if (!depth)
+		if (depth == -1)
 			depth = RSDepth(RSptr->info);
 	}
 	if (sync == -1) {
 		sync = 0;
-		if (yres < 480)
+		if (yres < 400)
+			sync |= FB_SYNC_HOR_HIGH_ACT;
+		else if (yres < 480)
 			sync |= FB_SYNC_VERT_HIGH_ACT;
 	}
 	if (xres < 320)
@@ -5028,6 +5521,9 @@
 			if (tmp > pixclock) pixclock = tmp;
 		}
 	}
+	if ((depth == RSText8) && (!*ACCESS_FBINFO(fbcon.fontname))) {
+		strcpy(ACCESS_FBINFO(fbcon.fontname), "VGA8x8");
+	}
 	vesafb_defined.red = colors[depth-1].red;
 	vesafb_defined.green = colors[depth-1].green;
 	vesafb_defined.blue = colors[depth-1].blue;
@@ -5067,41 +5563,38 @@
 	ACCESS_FBINFO(fbcon.flags) = FBINFO_FLAG_DEFAULT;
 	ACCESS_FBINFO(hw_switch->reset(PMINFO hw));
 	ACCESS_FBINFO(video.len_usable) &= PAGE_MASK;
+#if defined(CONFIG_PPC)
 #if defined(CONFIG_FB_COMPAT_XPMAC)
 	strcpy(ACCESS_FBINFO(matrox_name), "MTRX,");	/* OpenFirmware naming convension */
-	strcat(ACCESS_FBINFO(matrox_name), b->name);
+	strncat(ACCESS_FBINFO(matrox_name), b->name, 26);
 	if (!console_fb_info)
 		console_fb_info = &ACCESS_FBINFO(fbcon);
 #endif
-#if defined(CONFIG_PPC)
 	if ((xres <= 640) && (yres <= 480)) {
 		struct fb_var_screeninfo var;
+		int default_vmode = nvram_read_byte(NV_VMODE);
+		int default_cmode = nvram_read_byte(NV_CMODE);
 
-		if (default_vmode == VMODE_NVRAM)
-			default_vmode = nvram_read_byte(NV_VMODE);
 		if ((default_vmode <= 0) || (default_vmode > VMODE_MAX))
 			default_vmode = VMODE_640_480_60;
-		if (default_cmode == CMODE_NVRAM)
-			default_cmode = nvram_read_byte(NV_CMODE);
 		if ((default_cmode < CMODE_8) || (default_cmode > CMODE_32))
 			default_cmode = CMODE_8;
 		if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
 			var.accel_flags = vesafb_defined.accel_flags;
-			vesafb_defined = var;
+			var.xoffset = var.yoffset = 0;
+			vesafb_defined = var; /* Note: mac_vmode_to_var() doesnot set all parameters */
 		}
 	}
 #endif
 	{
 		int pixel_size = vesafb_defined.bits_per_pixel;
-		int avamem = ACCESS_FBINFO(video.len_usable);
 
-		vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO xres, pixel_size);
+		vesafb_defined.xres_virtual = matroxfb_pitch_adjust(PMINFO vesafb_defined.xres, pixel_size);
 		if (nopan) {
 			vesafb_defined.yres_virtual = vesafb_defined.yres;
 		} else {
-			vesafb_defined.yres_virtual = (avamem * 8 / (pixel_size * vesafb_defined.xres_virtual)) & ~0x1F;
-			if (vesafb_defined.yres_virtual < vesafb_defined.yres)
-				vesafb_defined.yres_virtual = vesafb_defined.yres;
+			vesafb_defined.yres_virtual = 65536; /* large enough to be INF, but small enough
+			                                        to yres_virtual * xres_virtual < 2^32 */
 		}
 	}
 	if (matroxfb_set_var(&vesafb_defined, -2, &ACCESS_FBINFO(fbcon))) {
@@ -5180,6 +5673,7 @@
 				ACCESS_FBINFO(devflags.inverse) = inverse;
 				ACCESS_FBINFO(devflags.novga) = novga;
 				ACCESS_FBINFO(devflags.nobios) = nobios;
+				ACCESS_FBINFO(devflags.noinit) = noinit;
 				ACCESS_FBINFO(devflags.nopciretry) = no_pci_retry;
 				ACCESS_FBINFO(devflags.mga_24bpp_fix) = inv24;
 				ACCESS_FBINFO(devflags.precise_width) = option_precise_width;
@@ -5234,9 +5728,11 @@
 }
 
 #if defined(CONFIG_FB_OF)
-__initfunc(void matrox_of_init(struct device_node *dp)) {
+__initfunc(int matrox_of_init(struct device_node *dp)) {
 	DBG("matrox_of_init");
 	matrox_init();
+	if (!fb_list) return -ENXIO;
+	return 0;
 }
 #endif	/* CONFIG_FB_OF */
 
@@ -5258,6 +5754,8 @@
 MODULE_PARM_DESC(novga, "VGA I/O (0x3C0-0x3DF) disabled (0 or 1=disabled) (default=0)");
 MODULE_PARM(nobios, "i");
 MODULE_PARM_DESC(nobios, "Disables ROM BIOS (0 or 1=disabled) (default=do not change BIOS state)"); 
+MODULE_PARM(noinit, "i");
+MODULE_PARM_DESC(noinit, "Disables W/SG/SD-RAM and bus interface initialization (0 or 1=do not initialize) (default=0)");
 MODULE_PARM(inv24, "i");
 MODULE_PARM_DESC(inv24, "Inverts clock polarity for 24bpp and loop frequency > 100MHz (default=do not invert polarity)");
 MODULE_PARM(inverse, "i");
@@ -5270,7 +5768,7 @@
 MODULE_PARM_DESC(dev, "Multihead support, attach to device ID (0..N) (default=first working)");
 #endif
 MODULE_PARM(vesa, "i");
-MODULE_PARM_DESC(vesa, "Startup videomode (0x100-0x1FF) (default=0x101)");
+MODULE_PARM_DESC(vesa, "Startup videomode (0x000-0x1FF) (default=0x101)");
 MODULE_PARM(xres, "i");
 MODULE_PARM_DESC(xres, "Horizontal resolutioni (px), overrides xres from vesa (default=vesa)");
 MODULE_PARM(yres, "i");
@@ -5292,7 +5790,7 @@
 MODULE_PARM(sync, "i");
 MODULE_PARM_DESC(sync, "Sync polarity, overrides sync from vesa (default=vesa)");
 MODULE_PARM(depth, "i");
-MODULE_PARM_DESC(depth, "Color depth (8,15,16,24,32) (default=vesa)");
+MODULE_PARM_DESC(depth, "Color depth (0=text,8,15,16,24,32) (default=vesa)");
 MODULE_PARM(maxclk, "i");
 MODULE_PARM_DESC(maxclk, "Startup maximal clock, 0-999MHz, 1000-999999kHz, 1000000-INF Hz");
 MODULE_PARM(fh, "i");
@@ -5309,7 +5807,7 @@
 MODULE_PARM(grayscale, "i");
 MODULE_PARM_DESC(grayscale, "Sets display into grayscale. Works perfectly with paletized videomode (4, 8bpp), some limitations apply to 16, 24 and 32bpp videomodes (default=nograyscale)");
 MODULE_PARM(cross4MB, "i");
-MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. It cannot at least on Millennium (I/II).");
+MODULE_PARM_DESC(cross4MB, "Specifies that 4MB boundary can be in middle of line. (default=autodetected)");
 
 __initfunc(int init_module(void)) {
 
@@ -5321,7 +5819,7 @@
 #endif /* DEBUG */
 
 	if (depth == 0)
-		depth = 0;	/* default */
+		depth = RSText;
 	else if (depth == 4)
 		depth = RS4bpp;
 	else if (depth == 8)
@@ -5334,9 +5832,9 @@
 		depth = RS24bpp;
 	else if (depth == 32)
 		depth = RS32bpp;
-	else {
+	else if (depth != -1) {
 		printk(KERN_ERR "matroxfb: depth %d is not supported, using default\n", depth);
-		depth = 0;
+		depth = -1;
 	}
 	matrox_init();
 	if (!fb_list) return -ENXIO;
diff -u --recursive --new-file v2.1.131/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.1.131/linux/drivers/video/offb.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/offb.c	Mon Dec 21 14:48:04 1998
@@ -302,7 +302,7 @@
 extern void chips_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_CT65550 */
 #ifdef CONFIG_FB_MATROX
-extern void matrox_of_init(struct device_node *dp);
+extern int matrox_of_init(struct device_node *dp);
 #endif /* CONFIG_FB_MATROX */
 #ifdef CONFIG_FB_CONTROL
 extern void control_of_init(struct device_node *dp);
@@ -329,43 +329,43 @@
     /* If we're booted from BootX... */
     if (prom_num_displays == 0 && boot_infos != 0) {
 	unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;
-	if (!ofonly) {
-	    /* find the device node corresponding to the macos display */
-	    for (dp = displays; dp != NULL; dp = dp->next) {
-		int i;
-		/*
-		 * Grrr...  It looks like the MacOS ATI driver
-		 * munges the assigned-addresses property (but
-		 * the AAPL,address value is OK).
-		 */
-		if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
-		    unsigned int *ap = (unsigned int *)
-			get_property(dp, "AAPL,address", NULL);
-		    if (ap != NULL) {
-			dp->addrs[0].address = *ap;
-			dp->addrs[0].size = 0x01000000;
-		    }
+	/* find the device node corresponding to the macos display */
+	for (dp = displays; dp != NULL; dp = dp->next) {
+	    int i;
+	    /*
+	     * Grrr...  It looks like the MacOS ATI driver
+	     * munges the assigned-addresses property (but
+	     * the AAPL,address value is OK).
+	     */
+	    if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {
+		unsigned int *ap = (unsigned int *)
+		    get_property(dp, "AAPL,address", NULL);
+		if (ap != NULL) {
+		    dp->addrs[0].address = *ap;
+		    dp->addrs[0].size = 0x01000000;
 		}
-		/*
-		 * See if the display address is in one of the address
-		 * ranges for this display.
-		 */
-		for (i = 0; i < dp->n_addrs; ++i) {
-		    if (dp->addrs[i].address <= addr
-			&& addr < dp->addrs[i].address + dp->addrs[i].size)
-			break;
-		}
-		if (i < dp->n_addrs) {
-		    printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
-		    macos_display = dp;
+	    }
+	    /*
+	     * See if the display address is in one of the address
+	     * ranges for this display.
+	     */
+	    for (i = 0; i < dp->n_addrs; ++i) {
+		if (dp->addrs[i].address <= addr
+		    && addr < dp->addrs[i].address + dp->addrs[i].size)
 		    break;
-		}
+	    }
+	    if (i < dp->n_addrs) {
+		printk(KERN_INFO "MacOS display is %s\n", dp->full_name);
+		macos_display = dp;
+		break;
 	    }
 	}
 
 	/* initialize it */
-	if (macos_display == NULL || !offb_init_driver(macos_display)) {
-	    offb_init_fb("MacOS display", "MacOS display",
+	if (ofonly || macos_display == NULL 
+	    || !offb_init_driver(macos_display)) {
+	    offb_init_fb(macos_display? macos_display->name: "MacOS display",
+			 macos_display? macos_display->full_name: "MacOS display",
 			 boot_infos->dispDeviceRect[2],
 			 boot_infos->dispDeviceRect[3],
 			 boot_infos->dispDeviceDepth,
@@ -403,7 +403,7 @@
 	return 1;
 #endif /* CONFIG_FB_S3TRIO */
 #ifdef CONFIG_FB_IMSTT
-    if (!strncmp(dp->name, "IMS,tt128mb", 11)) {
+    if (!strncmp(dp->name, "IMS,tt", 6)) {
 	imsttfb_of_init(dp);
 	return 1;
     }
@@ -524,7 +524,8 @@
 
 	/* XXX kludge for ati */
     if (strncmp(name, "ATY,", 4) == 0) {
-	info->cmap_adr = ioremap(address + 0x7ff000, 0x1000) + 0xcc0;
+	unsigned long base = address & 0xff000000UL;
+	info->cmap_adr = ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
 	info->cmap_data = info->cmap_adr + 1;
     }
 
@@ -674,9 +675,10 @@
 	display_info.disp_reg_address = 0;
 	/* XXX kludge for ati */
 	if (strncmp(name, "ATY,", 4) == 0) {
-	    display_info.disp_reg_address = address + 0x7ffc00;
-	    display_info.cmap_adr_address = address + 0x7ffcc0;
-	    display_info.cmap_data_address = address + 0x7ffcc1;
+	    unsigned long base = address & 0xff000000UL;
+	    display_info.disp_reg_address = base + 0x7ffc00;
+	    display_info.cmap_adr_address = base + 0x7ffcc0;
+	    display_info.cmap_data_address = base + 0x7ffcc1;
 	}
 	console_fb_info = &info->info;
     }
diff -u --recursive --new-file v2.1.131/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.1.131/linux/drivers/video/retz3fb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/retz3fb.c	Mon Dec 21 14:48:04 1998
@@ -178,7 +178,11 @@
 	"640x480", {		/* 640x480, 8 bpp */
 	    640, 480, 640, 480, 0, 0, 8, 0,
 	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+#if 1
+	    0, 0, -1, -1, FB_ACCEL_NONE, 39722, 48, 16, 33, 10, 96, 2,
+#else
 	    0, 0, -1, -1, FB_ACCELF_TEXT, 38461, 28, 32, 12, 10, 96, 2,
+#endif
 	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
 	}
     },
@@ -194,8 +198,24 @@
 	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
 	}
     },
+    {
+	"800x600-60", {		/* 800x600, 8 bpp */
+	    800, 600, 800, 600, 0, 0, 8, 0,
+	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	    0, 0, -1, -1, FB_ACCELF_TEXT, 25000, 88, 40, 23, 1, 128, 4,
+	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}
+    },
+    {
+	"800x600-70", {		/* 800x600, 8 bpp */
+	    800, 600, 800, 600, 0, 0, 8, 0,
+	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+	    0, 0, -1, -1, FB_ACCELF_TEXT, 22272, 40, 24, 15, 9, 144, 12,
+	    FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
+	}
+    },
     /*
-     ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
+      ModeLine "1024x768i" 45 1024 1064 1224 1264 768 777 785 817 interlace
 	       < name >   DCF HR  SH1  SH2  HFL  VR  SV1 SV2 VFL
      */
     {
@@ -205,14 +225,24 @@
 	    0, 0, -1, -1, FB_ACCELF_TEXT, 22222, 40, 40, 32, 9, 160, 8,
 	    FB_SYNC_COMP_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_INTERLACED
 	}
-    }, {
+    },
+    {
+	"1024x768", {
+	    1024, 768, 1024, 768, 0, 0, 8, 0, 
+	    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 
+	    0, 0, -1, -1, FB_ACCEL_NONE, 12500, 92, 112, 31, 2, 204, 4,
+	    FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
+	 }
+    },
+    {
 	"640x480-16", {		/* 640x480, 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, 0, 38461/2, 28, 32, 12, 10, 96, 2,
 	    FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,FB_VMODE_NONINTERLACED
 	}
-    }, {
+    },
+    {
 	"640x480-24", {		/* 640x480, 24 bpp */
 	    640, 480, 640, 480, 0, 0, 24, 0,
 	    {8, 8, 8}, {8, 8, 8}, {8, 8, 8}, {0, 0, 0},
@@ -421,7 +451,7 @@
 	data.h_total	= (hback / 8) + (xres / 8)
 			+ (hfront / 8) + (hsync / 8) - 1 /* + 1 */;
 	data.h_dispend	= ((xres + bpp - 1)/ 8) - 1;
-	data.h_bstart	= xres / 8 /* + 1 */;
+	data.h_bstart	= xres / 8 - 1 /* + 1 */;
 
 	data.h_bstop	= data.h_total+1 + 2 + 1;
 	data.h_sstart	= (xres / 8) + (hfront / 8) + 1;
@@ -430,7 +460,7 @@
 	data.v_total	= yres + vfront + vsync + vback - 1;
 
 	data.v_dispend	= yres - 1;
-	data.v_bstart	= yres;
+	data.v_bstart	= yres - 1;
 
 	data.v_bstop	= data.v_total;
 	data.v_sstart	= yres + vfront - 1 - 2;
@@ -1198,7 +1228,7 @@
 	case 8:
 		if (display->var.accel_flags & FB_ACCELF_TEXT) {
 		    display->dispsw = &fbcon_retz3_8;
-#warning FIXME: We should reinit the graphics engine here
+		    retz3_set_video(info, &display->var, &zinfo->current_par);
 		} else
 		    display->dispsw = &fbcon_cfb8;
 		break;
@@ -1266,7 +1296,6 @@
 			case 8:
 				if (var->accel_flags & FB_ACCELF_TEXT) {
 					display->dispsw = &fbcon_retz3_8;
-#warning FIXME: We should reinit the graphics engine here
 				} else
 					display->dispsw = &fbcon_cfb8;
 				break;
@@ -1280,9 +1309,14 @@
 				display->dispsw = &fbcon_dummy;
 				break;
 			}
-/*
-	retz3fb_set_disp(con, info);
-*/
+			/*
+			 * We still need to find a way to tell the X
+			 * server that the video mem has been fiddled with
+			 * so it redraws the entire screen when switching
+			 * between X and a text console.
+			 */
+			retz3_set_video(info, var, &zinfo->current_par);
+
 			if (info->changevar)
 				(*info->changevar)(con);
 		}
diff -u --recursive --new-file v2.1.131/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.1.131/linux/drivers/video/sbusfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/sbusfb.c	Mon Dec 21 14:48:04 1998
@@ -1134,9 +1134,11 @@
 		int root, node;
 		root = prom_getchild(prom_root_node);
 		for (node = prom_searchsiblings(root, "SUNW,ffb"); node;
-		     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb")) {
+		     node = prom_searchsiblings(prom_getsibling(node), "SUNW,ffb"))
+			sbusfb_init_fb(node, prom_root_node, FBTYPE_CREATOR, NULL);
+		for (node = prom_searchsiblings(root, "SUNW,afb"); node;
+		     node = prom_searchsiblings(prom_getsibling(node), "SUNW,afb"))
 			sbusfb_init_fb(node, prom_root_node, FBTYPE_CREATOR, NULL);
-		}
 	}
 #endif
 #ifdef CONFIG_SUN4
diff -u --recursive --new-file v2.1.131/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.1.131/linux/drivers/video/tgafb.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/tgafb.c	Mon Dec 21 14:48:04 1998
@@ -19,6 +19,10 @@
  *
  *	- Hardware cursor (useful for other graphics boards too)
  *
+ *	- Support for more resolutions
+ *
+ *	- Some redraws can stall kernel for several seconds
+ *
  * KNOWN PROBLEMS/TO DO ==================================================== */
 
 #include <linux/module.h>
@@ -800,18 +804,56 @@
 }
 
     /*
-     *  Blank the display.
+     *  Blank and unblank the display.
      */
 
 static void tgafbcon_blank(int blank, struct fb_info *info)
 {
-    /* Should also do stuff here for vesa blanking  -tor */
+    static int tga_vesa_blanked = 0;
+    u32 vhcr, vvcr;
+    unsigned long flags;
+    
+    save_flags(flags);
+    cli();
+
+    vhcr = TGA_READ_REG(TGA_HORIZ_REG);
+    vvcr = TGA_READ_REG(TGA_VERT_REG);
+
+    switch (blank) {
+    case 0: /* Unblanking */
+        if (tga_vesa_blanked) {
+	   TGA_WRITE_REG(vhcr & 0xbfffffff, TGA_HORIZ_REG);
+	   TGA_WRITE_REG(vvcr & 0xbfffffff, TGA_VERT_REG);
+	   tga_vesa_blanked = 0;
+	}
+ 	TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+	break;
 
-    if (blank > 0) {
+    case 1: /* Normal blanking */
 	TGA_WRITE_REG(0x03, TGA_VALID_REG); /* SCANNING and BLANK */
-    } else {
-	TGA_WRITE_REG(0x01, TGA_VALID_REG); /* SCANNING */
+	break;
+
+    case 2: /* VESA blank (vsync off) */
+	TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
+	TGA_WRITE_REG(0x02, TGA_VALID_REG); /* BLANK */
+	tga_vesa_blanked = 1;
+	break;
+
+    case 3: /* VESA blank (hsync off) */
+	TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
+	TGA_WRITE_REG(0x02, TGA_VALID_REG); /* BLANK */
+	tga_vesa_blanked = 1;
+	break;
+
+    case 4: /* Poweroff */
+	TGA_WRITE_REG(vhcr | 0x40000000, TGA_HORIZ_REG);
+	TGA_WRITE_REG(vvcr | 0x40000000, TGA_VERT_REG);
+	TGA_WRITE_REG(0x02, TGA_VALID_REG); /* BLANK */
+	tga_vesa_blanked = 1;
+	break;
     }
+
+    restore_flags(flags);
 }
 
     /*
diff -u --recursive --new-file v2.1.131/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.1.131/linux/drivers/video/virgefb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/virgefb.c	Mon Dec 21 14:48:04 1998
@@ -32,6 +32,7 @@
 #include <asm/irq.h>
 #include <asm/pgtable.h>
 #include <asm/amigahw.h>
+#include <asm/io.h>
 
 #include <video/s3blit.h>
 #include <video/fbcon.h>
diff -u --recursive --new-file v2.1.131/linux/fs/ChangeLog linux/fs/ChangeLog
--- v2.1.131/linux/fs/ChangeLog	Tue Oct 25 09:10:14 1994
+++ linux/fs/ChangeLog	Fri Dec 18 07:09:35 1998
@@ -8,3 +8,169 @@
 	* fcntl.c (sys_fcntl): Add more of a security check to the
 		F_SETOWN fcntl().
 
+[Tons of changes missed, indeed. This list is worth restarting since
+at least some fixes WILL break third-party filesystems. Sorry, but
+there was no other way to fix rmdir/rename deadlock, for one.]
+
+Wed Dec  2 (Linus, fill the rest, please)
+
+	* namei.c (do_rmdir) and rmdir method in filesystems:
+		Locking of directory we remove was taken to VFS.
+		See comments in do_rmdir(). Unfixed filesystems
+		will bloody likely deadlock in rmdir().
+
+Thu Dec  3 17:25:31 1998  Al Viro (viro@math.psu.edu)
+
+	* namei.c (do_rmdir):
+		Reject non-directories here.
+		Two (probably) obsolete checks moved here too: we fail if
+		the directory we remove is the same as parent (BUG: we
+		serve mountpoints later) or if it lives on a different
+		device.
+	* sysv/namei.c (sysv_rmdir):	See sysv/CHANGES
+
+Fri Dec  4 00:54:12 1998  AV
+
+	* namei.c (check_sticky): New function check_sticky(dir, inode).
+		If dir is sticky check whether we can unlink/rmdir/rename
+		the inode. Returns 1 if we can't. If dir isn't sticky -
+		return 0 (i.e. no objections). Some filesystems require
+		suser() here; some are fine with CAP_FOWNER. The later
+		seems more reasonable.
+	* namei.c (do_rmdir):
+		Moved the check for sticky bit here.
+	* affs/{inode,namei}.c:
+		All AFFS directories have sticky semantics (i.e. non-owner
+		having write permisssions on directory can unlink/rmdir/rename
+		only the files he owns), but AFFS didn't set S_ISVTX on them.
+		Fixed. NB: maybe this behaviour should be controlled by mount
+		option. Obvious values being 'sticky' (current behaviour),
+		'nonsticky' (normal behaviour) and maybe some play on 'D'
+		permissions bit. FIXME.
+	* qnx4/namei.c (qnx4_rmdir):
+		Plugged inode leak.
+	* ufs/namei.c (ufs_rmdir):
+		Changed handling of busy directory to new scheme.
+
+Fri Dec  4 10:30:58 1998  AV
+
+	* namei.c (VFS_rmdir): New function. It gets inode of the parent and
+		dentry of the victim, does all checks and applies fs-specific
+		rmdir() method. It should be called with semaphores down
+		on both the victim and its parent and with bumped d_count on
+		victim (see comments in do_rmdir).
+	* include/linux/fs.h: Added VFS_rmdir
+	* kernel/ksyms.c: Added VFS_rmdir to export list (for NFSD).
+	* nfsd/vfs.c: Fixed rmdir handling.
+
+Tue Dec  8 05:55:08 1998  AV
+	* vfat/namei.c: Fixed the bug in vfat_rename() introduced in the
+		first round of rmdir fixes.
+
+Wed Dec  9 03:06:10 1998  AV
+	* namei.c (do_rename): part of fs-independent checks had been moved
+		here (sticky bit handling, type mismatches). Cases of
+		the source or target being append-only or immutable also went
+		here - if we check it for parent we could as well do it for
+		children.
+	* {affs,ext2,minix,sysv,ufs}/namei.c (do_*_rename):
+		Removed tests that went to VFS, it simplified the code big way.
+		Fixed a race in check for empty target - we should check for
+		extra owners _before_ checking for emptiness, not after it.
+	* {ext2,ufs}/namei.c (do_*_rename):
+		VERY nasty bug shot: if somebody mkdired /tmp/cca01234, went
+		there, rmdired '.', waited till somebody created a file with
+		the same name and said mv . /tmp/goodbye_sticky_bit... Well,
+		goodbye sticky bit. Down, not across!
+	* {minix,sysv}/namei.c (do_*_rename):
+		Incorrect check for other owners (i_count instead of d_count).
+		Fixed.
+	* vfat: Looks like the changes above fixed a bug in VFAT - this beast
+		used to allow renaming file over directory and vice versa.
+
+Wed Dec  9 08:00:27 1998  AV
+	* namei.c (VFS_rename): New function. It gets the same arguments as
+		->rename() method, does all checks and applies fs-specific
+		rmdir() method. It should be called with semaphores down
+		on both parents.
+	* include/linux/fs.h: Added VFS_rename
+	* kernel/ksyms.c: Added VFS_rename to export list (for NFSD).
+	* nfsd/vfs.c: Changed rename handling (switched to VFS_rename).
+
+Wed Dec  9 18:16:27 1998  AV
+	* namei.c (do_unlink): handling of sticky bit went here.
+	* {affs,ext2,minix,qnx4,sysv,ufs}/namei.c (*_unlink):
+		removed handling of sticky bit.
+	* qnx4/namei.c (qnx4_unlink):
+		Yet another inode leak. Fixed.
+
+Thu Dec 10 04:55:26 1998  AV
+	* {ext2,minix,sysv,ufs}/namei.c (*_mknod):
+		removed meaningless code handling attempts to mknod symlinks
+		and directories. VFS protects us from _that_ and if this code
+		would ever be called we'ld get a filesystem corruption.
+
+Thu Dec 10 16:58:50 1998  AV
+	* namei.c (do_rename): Fixed dentry leak that had been introduced by
+		the first round of rmdir fixes.
+
+Fri Dec 11 14:57:17 1998  AV
+	* msdos/namei.c (msdos_rmdir): Fixed race in emptiness check.
+
+Sat Dec 12 19:59:57 1998  AV
+	* msdos/namei.c (msdos_mkdir): Fixed the evil breakage introduced by
+		the changes of rmdir locking scheme. We shouldn't call
+		msdos_rmdir from there.
+
+Sun Dec 13 02:05:16 1998  AV
+	* namei.c (do_unlink):
+		Added new function: vfs_unlink, with the same arguments as
+		->unlink() method.
+	* kernel/ksyms.c: Made it exported.
+	* include/linux/fs.h: Added prototype.
+	* nfsd/vfs.c: Changed handling of unlink (switched to vfs_unlink)
+	* {ext2,ufs}/namei.c (*_unlink): moved handling of imm./append-only to
+		VFS.
+
+Wed Dec 16 06:10:04 1998  AV
+	* namei.c (may_create, may_delete): New inline functions.
+		They check whether creation/deletion is permitted.
+		Checks from other places of namei.c went there.
+		Looks like originally I misread permission-related stuff
+		both here and in nfsd. In particular, checks for
+		immutable are done in permission(). D'oh.
+	* unlink on directory should return -EISDIR, not -EPERM as it used to
+		do. Fixed.
+	* rmdir of immutable/append-only directory shouldn't be allowed. Fixed.
+
+Remains unfixed:
+	* UMSDOS_rename is broken. Call it with the dest. existing and being an
+		empty directory and you've got EBUSY. At least it doesn't do
+		any harm, so that will wait several days till rename cleanup.
+		Sigh... It will wait a bit more. Problems with fat-derived
+		filesystems are much worse than I thought. Idea of changing
+		inode under dentry is broken by design - guess where the
+		semaphore sits, for one.
+	* umsdos: weird. rename() shouldn't return -EEXIST. BTW, manpage
+		for rename(2) is obviously bogus - it mentions EEXIST and
+		on the next line (correctly) says that EINVAL should be
+		returned. Under the same conditions.
+	* rename's handling of races is, erm, not optimal. Looks like I know
+		what to do, but this thing needs some more cleanup - we can
+		take care of almost all races in VFS and be much more graceful
+		wrt locking. Moreover, it would give strong lookup atomicity.
+		But it's a lot of changes to lookup and dcache code, so it will
+		go after the fs drivers' cleanup.
+	* hfs allows mknod. Only for regular files ;-/ IMHO it's bogus.
+	* affs allows HARD links to directories. VFS is, to put it politely,
+		not too ready to cope with _that_. And I'm not sure it should
+		be - looks like they are pretty much similar to symlinks.
+	* truncate doesn't give a damn about IO errors and disk overflows (on
+		braindead filesystems). I've submitted a patch to Linus, but
+		looks like it wasn't applied.
+	* msdos: shouldn't we treat SYS as IMMUTABLE? Makes sense, IMHO.
+	* minix, qnx and sysv do NOT allow to mkdir sticky directories.
+	* {minix,sysv}/namei.c (do_{minix,syv}_{rename,unlink}):
+		Stuff related to retries still needs cleanup/fixing.
+		Looks like I've found an extremely low-probability race
+		there...
diff -u --recursive --new-file v2.1.131/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.1.131/linux/fs/affs/inode.c	Fri May  8 23:14:50 1998
+++ linux/fs/affs/inode.c	Wed Dec 16 12:17:21 1998
@@ -170,8 +170,11 @@
 		} else {
 			inode->i_op = &affs_file_inode_operations;
 		}
-	} else if (S_ISDIR(inode->i_mode))
+	} else if (S_ISDIR(inode->i_mode)) {
+		/* Maybe it should be controlled by mount parameter? */
+		inode->i_mode |= S_ISVTX;
 		inode->i_op = &affs_dir_inode_operations;
+	}
 	else if (S_ISLNK(inode->i_mode))
 		inode->i_op = &affs_symlink_inode_operations;
 }
diff -u --recursive --new-file v2.1.131/linux/fs/affs/namei.c linux/fs/affs/namei.c
--- v2.1.131/linux/fs/affs/namei.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/affs/namei.c	Fri Dec 18 07:09:35 1998
@@ -241,10 +241,6 @@
 		goto unlink_done;
 
 	inode  = dentry->d_inode;
-	retval = -EPERM;
-	if (current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto unlink_done;
 
 	if ((retval = affs_remove_header(bh,inode)) < 0)
 		goto unlink_done;
@@ -319,7 +315,7 @@
 	error       = affs_add_entry(dir,NULL,inode,dentry,ST_USERDIR);
 	if (error)
 		goto out_iput;
-	inode->i_mode = S_IFDIR | (mode & 0777 & ~current->fs->umask);
+	inode->i_mode = S_IFDIR | S_ISVTX | (mode & 0777 & ~current->fs->umask);
 	inode->u.affs_i.i_protect = mode_to_prot(inode->i_mode);
 	d_instantiate(dentry,inode);
 	mark_inode_dirty(inode);
@@ -360,17 +356,6 @@
 	if (!(bh = affs_find_entry(dir,dentry,&ino)))
 		goto rmdir_done;
 
-	retval = -EPERM;
-        if (current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto rmdir_done;
-	if (inode->i_dev != dir->i_dev)
-		goto rmdir_done;
-	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-		goto rmdir_done;
-	retval = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto rmdir_done;
 	/*
 	 * Make sure the directory is empty and the dentry isn't busy.
 	 */
@@ -574,29 +559,21 @@
 		retval = 0;
 		goto end_rename;
 	}
-	if (new_inode && S_ISDIR(new_inode->i_mode)) {
-		retval = -EISDIR;
-		if (!S_ISDIR(old_inode->i_mode))
-			goto end_rename;
-		retval = -EINVAL;
-		if (is_subdir(new_dentry, old_dentry))
-			goto end_rename;
-		if (new_dentry->d_count > 1)
-			shrink_dcache_parent(new_dentry);
-		retval = -ENOTEMPTY;
-		if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
-			goto end_rename;
-		retval = -EBUSY;
-		if (new_dentry->d_count > 1)
-			goto end_rename;
-	}
 	if (S_ISDIR(old_inode->i_mode)) {
-		retval = -ENOTDIR;
-		if (new_inode && !S_ISDIR(new_inode->i_mode))
-			goto end_rename;
 		retval = -EINVAL;
 		if (is_subdir(new_dentry, old_dentry))
 			goto end_rename;
+		if (new_inode) {
+			if (new_dentry->d_count > 1)
+				shrink_dcache_parent(new_dentry);
+			retval = -EBUSY;
+			if (new_dentry->d_count > 1)
+				goto end_rename;
+			retval = -ENOTEMPTY;
+			if (!empty_dir(new_bh,AFFS_I2HSIZE(new_inode)))
+				goto end_rename;
+		}
+
 		if (affs_parent_ino(old_inode) != old_dir->i_ino)
 			goto end_rename;
 	}
diff -u --recursive --new-file v2.1.131/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.1.131/linux/fs/autofs/inode.c	Sun Nov  8 14:03:05 1998
+++ linux/fs/autofs/inode.c	Thu Dec 17 16:51:36 1998
@@ -300,8 +300,11 @@
 	struct autofs_sb_info *sbi =
 		(struct autofs_sb_info *) inode->i_sb->u.generic_sbp;
 
+	/* Initialize to the default case (stub directory) */
+
 	inode->i_op = NULL;
-	inode->i_mode = 0;
+	inode->i_op = &autofs_dir_inode_operations;
+	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
 	inode->i_nlink = 2;
 	inode->i_size = 0;
 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
@@ -324,7 +327,7 @@
 
 		n = ino - AUTOFS_FIRST_SYMLINK;
 		if ( n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
-			printk("autofs: Looking for bad symlink inode 0x%08x\n", (unsigned int) ino);
+			printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino);
 			return;
 		}
 		
@@ -335,10 +338,6 @@
 		inode->i_mtime = inode->i_ctime = sl->mtime;
 		inode->i_size = sl->len;
 		inode->i_nlink = 1;
-	} else {
-		/* All non-root directory inodes look the same */
-		inode->i_op = &autofs_dir_inode_operations;
-		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
 	}
 }
 
diff -u --recursive --new-file v2.1.131/linux/fs/autofs/root.c linux/fs/autofs/root.c
--- v2.1.131/linux/fs/autofs/root.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/autofs/root.c	Thu Dec 17 16:51:36 1998
@@ -223,7 +223,8 @@
 	sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 
 	oz_mode = autofs_oz_mode(sbi);
-	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n", current->pid, current->pgrp, sbi->catatonic, oz_mode));
+	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, oz_mode = %d\n",
+		 current->pid, current->pgrp, sbi->catatonic, oz_mode));
 
 	/*
 	 * Mark the dentry incomplete, but add it. This is needed so
@@ -395,6 +396,7 @@
 	struct autofs_sb_info *sbi = (struct autofs_sb_info *) dir->i_sb->u.generic_sbp;
 	struct autofs_dirhash *dh = &sbi->dirhash;
 	struct autofs_dir_ent *ent;
+	ino_t ino;
 
 	if ( !autofs_oz_mode(sbi) )
 		return -EPERM;
@@ -407,6 +409,7 @@
 		printk("autofs: Out of inode numbers -- what the heck did you do??\n");
 		return -ENOSPC;
 	}
+	ino = sbi->next_dir_ino++;
 
 	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
 	if ( !ent )
@@ -418,14 +421,14 @@
 		return -ENOSPC;
 	}
 
-	dir->i_nlink++;
-	d_instantiate(dentry, iget(dir->i_sb,ent->ino));
-
 	ent->hash = dentry->d_name.hash;
 	memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len));
-	ent->ino = sbi->next_dir_ino++;
+	ent->ino = ino;
 	ent->dentry = dentry;
 	autofs_hash_insert(dh,ent);
+
+	dir->i_nlink++;
+	d_instantiate(dentry, iget(dir->i_sb,ino));
 
 	return 0;
 }
diff -u --recursive --new-file v2.1.131/linux/fs/buffer.c linux/fs/buffer.c
--- v2.1.131/linux/fs/buffer.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/buffer.c	Mon Dec 21 15:27:41 1998
@@ -691,12 +691,12 @@
 		goto no_candidate;
 
 	for (; (*list_len) > 0; bh = bh->b_next_free, (*list_len)--) {
-		if (size != bh->b_size) {
+		if (size != bh->b_size && !buffer_touched(bh)) {
 			/* This provides a mechanism for freeing blocks
 			 * of other sizes, this is necessary now that we
 			 * no longer have the lav code.
 			 */
-			try_to_free_buffer(bh,&bh,1);
+			try_to_free_buffer(bh,&bh);
 			if (!bh)
 				break;
 			continue;
@@ -920,7 +920,6 @@
 				 put_last_lru(bh);
 			bh->b_flushtime = 0;
 		}
-		set_bit(BH_Touched, &bh->b_state);
 		return bh;
 	}
 
@@ -936,7 +935,7 @@
 	 */
 	init_buffer(bh, dev, block, end_buffer_io_sync, NULL);
 	bh->b_lru_time	= jiffies;
-	bh->b_state=(1<<BH_Touched);
+	bh->b_state=0;
 	insert_into_queues(bh);
 	return bh;
 
@@ -1063,6 +1062,7 @@
 	struct buffer_head * bh = getblk(dev, block, size);
 
 	if (bh) {
+		touch_buffer(bh);
 		if (buffer_uptodate(bh))
 			return bh;
 		ll_rw_block(READ, 1, &bh);
@@ -1101,6 +1101,7 @@
 
 	index = BUFSIZE_INDEX(bh->b_size);
 
+	touch_buffer(bh);
 	if (buffer_uptodate(bh))
 		return(bh);   
 	else ll_rw_block(READ, 1, &bh);
@@ -1638,8 +1639,7 @@
  * try_to_free_buffer() checks if all the buffers on this particular page
  * are unused, and free's the page if so.
  */
-int try_to_free_buffer(struct buffer_head * bh, struct buffer_head ** bhp,
-		       int priority)
+int try_to_free_buffer(struct buffer_head * bh, struct buffer_head ** bhp)
 {
 	unsigned long page;
 	struct buffer_head * tmp, * p;
@@ -1654,8 +1654,6 @@
 		if (tmp->b_count || buffer_protected(tmp) ||
 		    buffer_dirty(tmp) || buffer_locked(tmp) ||
 		    buffer_waiting(tmp))
-			return 0;
-		if (priority && buffer_touched(tmp))
 			return 0;
 		tmp = tmp->b_this_page;
 	} while (tmp != bh);
diff -u --recursive --new-file v2.1.131/linux/fs/coda/Makefile linux/fs/coda/Makefile
--- v2.1.131/linux/fs/coda/Makefile	Wed Jun 24 22:54:08 1998
+++ linux/fs/coda/Makefile	Fri Dec 18 12:45:00 1998
@@ -4,7 +4,7 @@
 
 O_TARGET := coda.o
 O_OBJS   := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o coda_linux.o\
-            symlink.o pioctl.o sysctl.o stats.o
+            symlink.o pioctl.o sysctl.o 
 M_OBJS   := $(O_TARGET)
 
 # If you want debugging output, please uncomment the following line.
diff -u --recursive --new-file v2.1.131/linux/fs/coda/cache.c linux/fs/coda/cache.c
--- v2.1.131/linux/fs/coda/cache.c	Thu Jul 16 18:09:28 1998
+++ linux/fs/coda/cache.c	Fri Dec 18 12:45:00 1998
@@ -306,11 +306,12 @@
 	return; 
 }
 
-void coda_purge_children(struct inode *inode)
+void coda_flag_inode_children(struct inode *inode, int flag)
 {
 	struct list_head *alias;
 	struct dentry *alias_de;
 
+	ENTRY;
 	if ( !inode ) 
 		return; 
 
@@ -324,7 +325,7 @@
 	alias = inode->i_dentry.next; 
 	while ( alias != &inode->i_dentry ) {
 		alias_de = list_entry(alias, struct dentry, d_alias);
-		coda_flag_children(alias_de, C_PURGE);
+		coda_flag_children(alias_de, flag);
 		shrink_dcache_parent(alias_de);
 		alias = alias->next;
 	}
diff -u --recursive --new-file v2.1.131/linux/fs/coda/cnode.c linux/fs/coda/cnode.c
--- v2.1.131/linux/fs/coda/cnode.c	Sat Sep  5 16:46:41 1998
+++ linux/fs/coda/cnode.c	Fri Dec 18 12:45:00 1998
@@ -40,7 +40,7 @@
 	else if (S_ISSOCK(inode->i_mode))
 		inode->i_op = NULL;
         else {
-                printk ("coda_read_inode: what's this? i_mode = %o\n", 
+                printk ("coda_fill_inode: what's this? i_mode = %o\n", 
 			inode->i_mode);
                 inode->i_op = NULL;
         }
@@ -68,7 +68,8 @@
 
 	error = venus_getattr(sb, fid, &attr);
 	if ( error ) {
-	    CDEBUG(D_CNODE, "coda_cnode_make: coda_getvattr returned %d for %s.\n", 
+	    CDEBUG(D_CNODE, 
+		   "coda_cnode_make: coda_getvattr returned %d for %s.\n", 
 		   error, coda_f2s(fid));
 	    *inode = NULL;
 	    return error;
@@ -92,8 +93,7 @@
 		INIT_LIST_HEAD(&(cnp->c_volrootlist));
 	} else {
 	        cnp->c_flags = 0;
-		CDEBUG(D_CNODE, "coda_cnode make on initialized"
-		       "inode %ld, %s!\n",
+		printk("coda_cnode make on initialized inode %ld, %s!\n",
 		       (*inode)->i_ino, coda_f2s(&cnp->c_fid));
 	}
 
diff -u --recursive --new-file v2.1.131/linux/fs/coda/coda_linux.c linux/fs/coda/coda_linux.c
--- v2.1.131/linux/fs/coda/coda_linux.c	Thu Jul 16 18:09:28 1998
+++ linux/fs/coda/coda_linux.c	Fri Dec 18 12:45:00 1998
@@ -44,8 +44,8 @@
 /* recognize special .CONTROL name */
 int coda_iscontrol(const char *name, size_t length)
 {
-	if ((CFS_CONTROLLEN == length) && 
-	    (strncmp(name, CFS_CONTROL, CFS_CONTROLLEN) == 0))
+	if ((CODA_CONTROLLEN == length) && 
+	    (strncmp(name, CODA_CONTROL, CODA_CONTROLLEN) == 0))
 		return 1;
 	return 0;
 }
@@ -104,7 +104,7 @@
         cred->cr_suid = (vuid_t) current->suid;
         cred->cr_fsuid = (vuid_t) current->fsuid;
 
-        cred->cr_gid = (vgid_t) current->gid;
+        cred->cr_groupid = (vgid_t) current->gid;
         cred->cr_egid = (vgid_t) current->egid;
         cred->cr_sgid = (vgid_t) current->sgid;
         cred->cr_fsgid = (vgid_t) current->fsgid;
@@ -142,6 +142,11 @@
 	if ( flags & O_TRUNC )  { 
 		CDEBUG(D_FILE, "--> C_O_TRUNC added\n");
 		coda_flags |= C_O_TRUNC;
+	}
+
+	if ( flags & O_CREAT )  { 
+		CDEBUG(D_FILE, "--> C_O_CREAT added\n");
+		coda_flags |= C_O_CREAT;
 	}
 
 	if ( flags & O_EXCL ) {
diff -u --recursive --new-file v2.1.131/linux/fs/coda/dir.c linux/fs/coda/dir.c
--- v2.1.131/linux/fs/coda/dir.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/coda/dir.c	Fri Dec 18 12:45:00 1998
@@ -45,16 +45,15 @@
 /* dentry ops */
 static int coda_dentry_revalidate(struct dentry *de);
 static void coda_dentry_delete(struct dentry *);
+
 /* support routines */
 static int coda_venus_readdir(struct file *filp, void *dirent, 
 			      filldir_t filldir);
 int coda_fsync(struct file *, struct dentry *dentry);
-static int coda_refresh_inode(struct dentry *dentry);
 
 int coda_crossvol_rename = 0;
 int coda_hasmknod = 0;
 
-
 struct dentry_operations coda_dentry_operations =
 {
 	coda_dentry_revalidate, /* revalidate */
@@ -119,24 +118,24 @@
 	size_t length = entry->d_name.len;
 	
         ENTRY;
-        CDEBUG(D_INODE, "name %s, len %d in ino %ld\n", 
-	       name, length, dir->i_ino);
-
-	if (!dir || !S_ISDIR(dir->i_mode)) {
-		printk("coda_lookup: inode is NULL or not a directory\n");
-		return -ENOTDIR;
-	}
 
 	dircnp = ITOC(dir);
 
-	if ( length > CFS_MAXNAMLEN ) {
+	if ( length > CODA_MAXNAMLEN ) {
 	        printk("name too long: lookup, %s (%*s)\n", 
 		       coda_f2s(&dircnp->c_fid), length, name);
 		return -ENAMETOOLONG;
 	}
-	
-	CDEBUG(D_INODE, "lookup: %*s in %s\n", length, name, 
-	       coda_f2s(&dircnp->c_fid));
+
+
+	if (!dir || !S_ISDIR(dir->i_mode)) {
+		printk("coda_lookup: inode is NULL or not a directory\n");
+		return -ENOTDIR;
+	}
+
+
+        CDEBUG(D_INODE, "name %s, len %d in ino %ld, fid %s\n", 
+	       name, length, dir->i_ino, coda_f2s(&dircnp->c_fid));
 
         /* control object, create inode on the fly */
         if (coda_isroot(dir) && coda_iscontrol(name, length)) {
@@ -152,8 +151,8 @@
 
 	res_inode = NULL;
 	if (!error) {
-		if (type & CFS_NOCACHE) {
-			type &= (~CFS_NOCACHE);
+		if (type & CODA_NOCACHE) {
+			type &= (~CODA_NOCACHE);
 			CDEBUG(D_INODE, "dropme set for %s\n", 
 			       coda_f2s(&resfid));
 			dropme = 1;
@@ -184,7 +183,7 @@
 
 int coda_permission(struct inode *inode, int mask)
 {
-        struct coda_inode_info *cp;
+        struct coda_inode_info *cp = ITOC(inode);
         int error;
  
         ENTRY;
@@ -192,7 +191,6 @@
 	coda_permission_stat.count++;
 
         if ( mask == 0 ) {
-                EXIT;
                 return 0;
         }
 
@@ -204,7 +202,6 @@
 	}
 
         cp = ITOC(inode);
-        CHECK_CNODE(cp);
 
         CDEBUG(D_INODE, "mask is %o\n", mask);
         error = venus_access(inode->i_sb, &(cp->c_fid), mask);
@@ -247,9 +244,8 @@
 		return -EPERM;
 
 	dircnp = ITOC(dir);
-        CHECK_CNODE(dircnp);
 
-        if ( length > CFS_MAXNAMLEN ) {
+        if ( length > CODA_MAXNAMLEN ) {
 		printk("name too long: create, %s(%s)\n", 
 		       coda_f2s(&dircnp->c_fid), name);
 		return -ENAMETOOLONG;
@@ -304,9 +300,8 @@
 		return -EPERM;
 
 	dircnp = ITOC(dir);
-        CHECK_CNODE(dircnp);
 
-        if ( length > CFS_MAXNAMLEN ) {
+        if ( length > CODA_MAXNAMLEN ) {
 		printk("name too long: mknod, %s(%s)\n", 
 		       coda_f2s(&dircnp->c_fid), name);
 		return -ENAMETOOLONG;
@@ -353,14 +348,13 @@
 		return -ENOENT;
 	}
 
-        if ( len > CFS_MAXNAMLEN )
+        if ( len > CODA_MAXNAMLEN )
                 return -ENAMETOOLONG;
 
 	if (coda_isroot(dir) && coda_iscontrol(name, len))
 		return -EPERM;
 
         dircnp = ITOC(dir);
-        CHECK_CNODE(dircnp);
 
 	CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n", 
 	       name, len, coda_f2s(&(dircnp->c_fid)), mode);
@@ -410,12 +404,11 @@
 
         dir_cnp = ITOC(dir_inode);
         cnp = ITOC(inode);
-        CHECK_CNODE(cnp);
 
 	CDEBUG(D_INODE, "old: fid: %s\n", coda_f2s(&(cnp->c_fid)));
 	CDEBUG(D_INODE, "directory: %s\n", coda_f2s(&(dir_cnp->c_fid)));
 
-        if ( len > CFS_MAXNAMLEN ) {
+        if ( len > CODA_MAXNAMLEN ) {
                 printk("coda_link: name too long. \n");
                 return -ENAMETOOLONG;
         }
@@ -428,8 +421,9 @@
 		++inode->i_count;
 		d_instantiate(de, inode);
 		inode->i_nlink++;
-	} else {
+	} else  {
 		d_drop(de);
+		return error;
 	}
 
         CDEBUG(D_INODE, "link result %d\n",error);
@@ -453,11 +447,11 @@
 	if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
 		return -EPERM;
 
-	if ( len > CFS_MAXNAMLEN )
+	if ( len > CODA_MAXNAMLEN )
                 return -ENAMETOOLONG;
 
 	symlen = strlen(symname);
-	if ( symlen > CFS_MAXPATHLEN )
+	if ( symlen > CODA_MAXPATHLEN )
                 return -ENAMETOOLONG;
 
         CDEBUG(D_INODE, "symname: %s, length: %d\n", symname, symlen);
@@ -467,10 +461,10 @@
 	 * an inode for the entry we have to drop it. 
 	 */
 	d_drop(de);
-
 	error = venus_symlink(dir_inode->i_sb, &(dir_cnp->c_fid), name, len, 
 			      symname, symlen);
 
+	/* mtime is no good anymore */
 	if ( !error ) {
 		dir_cnp->c_flags |= C_VATTR;
 	}
@@ -483,7 +477,7 @@
 /* destruction routines: unlink, rmdir */
 int coda_unlink(struct inode *dir, struct dentry *de)
 {
-        struct coda_inode_info *dircnp;
+        struct coda_inode_info *dircnp = ITOC(dir);
         int error;
 	const char *name = de->d_name.name;
 	int len = de->d_name.len;
@@ -491,25 +485,18 @@
 	ENTRY;
 	coda_vfs_stat.unlink++;
 
-        dircnp = ITOC(dir);
-        CHECK_CNODE(dircnp);
-
-        CDEBUG(D_INODE, " %s in %s, ino %ld\n", name , 
+        CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , 
 	       coda_f2s(&(dircnp->c_fid)), dir->i_ino);
 
-        /* this file should no longer be in the namecache! */
-
         error = venus_remove(dir->i_sb, &(dircnp->c_fid), name, len);
-
         if ( error ) {
                 CDEBUG(D_INODE, "upc returned error %d\n", error);
                 return error;
         }
 
-        /* cache management */
+        /* cache management: mtime has changed, ask Venus */
 	dircnp->c_flags |= C_VATTR;
 	de->d_inode->i_nlink--;
-
 	d_delete(de);
 
         return 0;
@@ -530,19 +517,12 @@
 		return -ENOENT;
 	}
         dircnp = ITOC(dir);
-        CHECK_CNODE(dircnp);
 
-	if (len > CFS_MAXNAMLEN)
+	if (len > CODA_MAXNAMLEN)
 		return -ENAMETOOLONG;
 
 	if (!list_empty(&de->d_hash))
 		return -EBUSY;
-
-	/* update i_nlink and free the inode before unlinking;
-	   if rmdir fails a new lookup set i_nlink right.*/
-	if (de->d_inode->i_nlink)
-		de->d_inode->i_nlink --;
-
 	error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len);
 
         if ( error ) {
@@ -550,6 +530,9 @@
                 return error;
         }
 
+	if (de->d_inode->i_nlink)
+		de->d_inode->i_nlink --;
+
         return 0;
 }
 
@@ -569,7 +552,7 @@
 	ENTRY;
 	coda_vfs_stat.rename++;
 
-        if ( (old_length > CFS_MAXNAMLEN) || new_length > CFS_MAXNAMLEN ) {
+        if ( (old_length > CODA_MAXNAMLEN) || new_length > CODA_MAXNAMLEN ) {
                 return -ENAMETOOLONG;
         }
 
@@ -641,8 +624,6 @@
         }
 
         cnp = ITOC(inode);
-        CHECK_CNODE(cnp);
-        
         if ( !cnp->c_ovp ) {
                 CDEBUG(D_FILE, "open inode pointer = NULL.\n");
                 return -EIO;
@@ -658,8 +639,8 @@
                 result = open_file.f_op->readdir(&open_file, dirent, filldir);
         }
 	coda_restore_codafile(inode, file, cnp->c_ovp, &open_file);
-	return result;
         EXIT;
+	return result;
 }
 
 /* ask venus to cache the file and return the inode of the container file,
@@ -673,15 +654,17 @@
         struct inode *cont_inode = NULL;
         unsigned short flags = f->f_flags & (~O_EXCL);
 	unsigned short coda_flags = coda_flags_to_cflags(flags);
+	struct coda_cred *cred;
 
         ENTRY;
 	coda_vfs_stat.open++;
-        
+
         CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", 
 	       f->f_dentry->d_inode->i_ino, f->f_dentry->d_count, flags);
 
         cnp = ITOC(i);
 
+
 	error = venus_open(i->i_sb, &(cnp->c_fid), coda_flags, &ino, &dev); 
 	if (error) {
 	        CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n",
@@ -700,6 +683,10 @@
 		return error;
 	}
 
+	CODA_ALLOC(cred, struct coda_cred *, sizeof(*cred));
+	coda_load_creds(cred);
+	f->private_data = cred;
+
         if (  cnp->c_ovp ) {
 		iput(cnp->c_ovp);
 		cnp->c_ovp = NULL;
@@ -722,10 +709,13 @@
         int error;
         unsigned short flags = (f->f_flags) & (~O_EXCL);
 	unsigned short cflags = coda_flags_to_cflags(flags);
+	struct coda_cred *cred;
 
         ENTRY;
 	coda_vfs_stat.release++;
 
+	cred = (struct coda_cred *)f->private_data;
+
         cnp =ITOC(i);
         CHECK_CNODE(cnp);
         CDEBUG(D_FILE,  
@@ -746,7 +736,10 @@
                 --cnp->c_owrite;
         }
 
-	error = venus_release(i->i_sb, &(cnp->c_fid), cflags);
+	error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred);
+
+	CODA_FREE(cred, sizeof(*cred));
+	f->private_data = NULL;
 
         CDEBUG(D_FILE, "coda_release: result: %d\n", error);
         return error;
@@ -759,96 +752,97 @@
  * beyond the current_dir pointer.
  */
 
-struct getdents_callback {
-	struct linux_dirent * current_dir;
-	struct linux_dirent * previous;
-	int count;
-	int error;
-};
+
+/* should be big enough to hold any single directory entry */
+#define DIR_BUFSIZE 2048
 
 static int coda_venus_readdir(struct file *filp, void *getdent, 
 			      filldir_t filldir)
 {
-        int result = 0,  offset, count, pos, error = 0;
+        int bufsize;
+	int offset = filp->f_pos; /* offset in the directory file */
+	int count = 0;
+	int pos = 0;      /* offset in the block we read */
+	int result = 0; /* either an error or # of entries returned */
 	int errfill;
-        caddr_t buff = NULL;
+        char *buff = NULL;
         struct venus_dirent *vdirent;
-        struct getdents_callback *dents_callback;
-        int string_offset;
-	int size;
-        char debug[255];
+        int string_offset = (int) (&((struct venus_dirent *)(0))->d_name);
+	int i;
 
         ENTRY;        
 
-        /* we also need the ofset of the string in the dirent struct */
-        string_offset = sizeof ( char )* 2  + sizeof(unsigned int) + 
-                        sizeof(unsigned short);
-
-        dents_callback = (struct getdents_callback *) getdent;
-
-        size = count =  dents_callback->count;
-        CODA_ALLOC(buff, void *, size);
-        if ( ! buff ) { 
+        CODA_ALLOC(buff, char *, DIR_BUFSIZE);
+        if ( !buff ) { 
                 printk("coda_venus_readdir: out of memory.\n");
                 return -ENOMEM;
         }
 
         /* we use this routine to read the file into our buffer */
-        result = read_exec(filp->f_dentry, filp->f_pos, buff, count, 1);
-        if ( result < 0) {
+        bufsize = read_exec(filp->f_dentry, filp->f_pos, buff, DIR_BUFSIZE, 1);
+        if ( bufsize < 0) {
                 printk("coda_venus_readdir: cannot read directory %d.\n",
-		       result);
-                error = result;
+		       bufsize);
+                result = bufsize;
                 goto exit;
         }
-        if ( result == 0) {
-                error = result;
+        if ( bufsize == 0) {
+                result = 0;
                 goto exit;
         }
-
+	
         /* Parse and write into user space. Filldir tells us when done! */
-        offset = filp->f_pos;
-        pos = 0;
-        CDEBUG(D_FILE, "offset %d, count %d.\n", offset, count);
+        CDEBUG(D_FILE, "buffsize: %d offset %d, count %d.\n", 
+	       bufsize, offset, count);
 
-        while ( pos + string_offset < result ) {
+	i = 0;
+	result = 0; 
+        while ( pos + string_offset < bufsize && i < 1024) {
                 vdirent = (struct venus_dirent *) (buff + pos);
 
                 /* test if the name is fully in the buffer */
-                if ( pos + string_offset + (int) vdirent->d_namlen >= result ){
+                if ( pos + string_offset + (int) vdirent->d_namlen >= bufsize ){
+			if ( result == 0 )
+				printk("CODA: Invalid directory cfino: %ld\n", 
+				       filp->f_dentry->d_inode->i_ino);
                         break;
                 }
-                
                 /* now we are certain that we can read the entry from buff */
 
-                /* for debugging, get the string out */
-                memcpy(debug, vdirent->d_name, vdirent->d_namlen);
-                *(debug + vdirent->d_namlen) = '\0';
-
                 /* if we don't have a null entry, copy it */
-                if ( vdirent->d_fileno ) {
+                if ( vdirent->d_fileno && vdirent->d_reclen ) {
                         int namlen  = vdirent->d_namlen;
                         off_t offs  = filp->f_pos; 
                         ino_t ino   = vdirent->d_fileno;
                         char *name  = vdirent->d_name;
-                        /* adjust count */
-                        count = dents_callback->count;
 
-			errfill = filldir(dents_callback,  name, namlen, 
+			errfill = filldir(getdent,  name, namlen, 
 					  offs, ino); 
-CDEBUG(D_FILE, "ino %ld, namlen %d, reclen %d, type %d, pos %d, string_offs %d, name %s, offset %d, count %d.\n", vdirent->d_fileno, vdirent->d_namlen, vdirent->d_reclen, vdirent->d_type, pos,  string_offset, debug, (u_int) offs, dents_callback->count);
-
-		      /* errfill means no space for filling in this round */
-                      if ( errfill < 0 ) break;
+CDEBUG(D_FILE, "entry %d: ino %ld, namlen %d, reclen %d, type %d, pos %d, string_offs %d, name %*s, offset %d, result: %d, errfill: %d.\n", i,vdirent->d_fileno, vdirent->d_namlen, vdirent->d_reclen, vdirent->d_type, pos,  string_offset, vdirent->d_namlen, vdirent->d_name, (u_int) offs, result, errfill);
+			/* errfill means no space for filling in this round */
+			if ( errfill < 0 ) {
+				result = 0;
+				break;
+			}
+                        /* adjust count */
+                        result++;
                 }
                 /* next one */
-                filp->f_pos += (unsigned int) vdirent->d_reclen;
+                filp->f_pos += vdirent->d_reclen;
+		if ( filp->f_pos > filp->f_dentry->d_inode->i_size )
+			break; 
+		if ( !vdirent->d_reclen ) {
+			printk("CODA: Invalid directory, cfino: %ld\n", 
+			       filp->f_dentry->d_inode->i_ino);
+			break;
+		}
                 pos += (unsigned int) vdirent->d_reclen;
+		i++;
         } 
 
 exit:
-        CODA_FREE(buff, size);
-        return error;
+        CODA_FREE(buff, DIR_BUFSIZE);
+        return result;
 }
 
 /* called when a cache lookup succeeds */
@@ -865,6 +859,10 @@
 		cii = ITOC(de->d_inode);
 		if (cii->c_flags & C_PURGE) 
 			valid = 0;
+		if (cii->c_flags & C_FLUSH) {
+			coda_flag_inode_children(inode, C_FLUSH);
+			valid = 0;
+		}
 	}
 	return valid ||  coda_isroot(de->d_inode);
 }
@@ -890,64 +888,74 @@
 }
 
 
-static int coda_refresh_inode(struct dentry *dentry)
+
+/*
+ * This is called when we want to check if the inode has
+ * changed on the server.  Coda makes this easy since the
+ * cache manager Venus issues a downcall to the kernel when this 
+ * happens 
+ */
+
+int coda_revalidate_inode(struct dentry *dentry)
 {
 	struct coda_vattr attr;
-	int error;
+	int error = 0;
 	int old_mode;
 	ino_t old_ino;
 	struct inode *inode = dentry->d_inode;
 	struct coda_inode_info *cii = ITOC(inode);
 
 	ENTRY;
-	
-	error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
-	if ( error ) { 
-		make_bad_inode(inode);
-		return -EIO;
-	}
+	CDEBUG(D_INODE, "revalidating: %*s/%*s\n", 
+	       dentry->d_name.len, dentry->d_name.name,
+	       dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);
 
-	/* this inode may be lost if:
-            - it's type changed
-            - it's ino changed 
-	*/
-	old_mode = inode->i_mode;
-	old_ino = inode->i_ino;
-	coda_vattr_to_iattr(inode, &attr);
+	if ( cii->c_flags == 0 )
+		return 0;
 
-	if ((inode->i_ino != old_ino) ||
-	    ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT))) {
+	/* Venus closed the device .... */
+	if ( cii->c_flags & C_DYING ) { 
 		make_bad_inode(inode);
-		inode->i_mode = old_mode;
 		return -EIO;
 	}
+
 	
-	cii->c_flags &= ~C_VATTR;
-	return 0;
-}
+	if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
+		error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
+		if ( error ) { 
+			make_bad_inode(inode);
+			return -EIO;
+		}
 
+		/* this inode may be lost if:
+		   - it's ino changed 
+		   - type changes must be permitted for repair and
+		   missing mount points.
+		*/
+		old_mode = inode->i_mode;
+		old_ino = inode->i_ino;
+		coda_vattr_to_iattr(inode, &attr);
 
-/*
- * This is called when we want to check if the inode has
- * changed on the server.  Coda makes this easy since the
- * cache manager Venus issues a downcall to the kernel when this 
- * happens 
- */
 
-int coda_revalidate_inode(struct dentry *dentry)
-{
-	int error = 0;
-	struct coda_inode_info *cii = ITOC(dentry->d_inode);
-
-	ENTRY;
-	CDEBUG(D_INODE, "revalidating: %*s/%*s\n", 
-	       dentry->d_name.len, dentry->d_name.name,
-	       dentry->d_parent->d_name.len, dentry->d_parent->d_name.name);
+		if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) {
+			printk("Coda: inode %ld, fid %s changed type!\n",
+			       inode->i_ino, coda_f2s(&(cii->c_fid)));
+		}
 
-	if (cii->c_flags & (C_VATTR | C_PURGE)) {
-		error = coda_refresh_inode(dentry);
+		/* the following can happen when a local fid is replaced 
+		   with a global one, here we lose and declar the inode bad */
+		if (inode->i_ino != old_ino) {
+			make_bad_inode(inode);
+			inode->i_mode = old_mode;
+			return -EIO;
+		}
+		
+		if ( cii->c_flags ) 
+			coda_flag_inode_children(inode, C_FLUSH);
+		
+		cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
 	}
 
-	return error;
+	return 0;
 }
 
diff -u --recursive --new-file v2.1.131/linux/fs/coda/inode.c linux/fs/coda/inode.c
--- v2.1.131/linux/fs/coda/inode.c	Thu Jul 16 18:09:28 1998
+++ linux/fs/coda/inode.c	Fri Dec 18 12:45:00 1998
@@ -36,7 +36,6 @@
 #include <linux/coda_fs_i.h>
 #include <linux/coda_cache.h>
 
-
 /* VFS super_block ops */
 static struct super_block *coda_read_super(struct super_block *, void *, int);
 static void coda_read_inode(struct inode *);
@@ -47,11 +46,6 @@
 static int coda_statfs(struct super_block *sb, struct statfs *buf, 
 		       int bufsiz);
 
-/* helper functions */
-static struct vcomm *coda_psinode2vcomm(struct inode *inode);
-static int coda_get_psdev(void *, struct inode **);
-static struct coda_sb_info *coda_psinode2sbi(struct inode *inode);
-
 /* exported operations */
 struct super_operations coda_super_operations =
 {
@@ -66,36 +60,28 @@
 	NULL			/* remount_fs */
 };
 
-/*
- * globals
- */
-struct coda_sb_info coda_super_info[MAX_CODADEVS];
-
-
 static struct super_block * coda_read_super(struct super_block *sb, 
 					    void *data, int silent)
 {
         struct inode *psdev = 0, *root = 0; 
 	struct coda_sb_info *sbi = NULL;
-	struct vcomm *vc = NULL;
+	struct venus_comm *vc = NULL;
         ViceFid fid;
 	kdev_t dev = sb->s_dev;
         int error;
 
 	ENTRY;
         MOD_INC_USE_COUNT; 
-        if (coda_get_psdev(data, &psdev))
-                goto error;
 
-        vc = coda_psinode2vcomm(psdev);
-        if ( !vc )
-	        goto error;
-	vc->vc_sb = sb;
-	vc->vc_inuse = 1;
-
-	sbi = coda_psinode2sbi(psdev);
-	if ( !sbi )
-	        goto error;
+        vc = &coda_upc_comm;
+	sbi = &coda_super_info;
+
+        if ( sbi->sbi_sb ) {
+		printk("Already mounted\n");
+		return NULL;
+	}
+
+	sbi->sbi_sb = sb;
         sbi->sbi_psdev = psdev;
 	sbi->sbi_vcomm = vc;
 	INIT_LIST_HEAD(&(sbi->sbi_cchead));
@@ -137,16 +123,13 @@
 	EXIT;  
         return sb;
 
-error:
-EXIT;  
+ error:
+	EXIT;  
 	MOD_DEC_USE_COUNT;
 	if (sbi) {
 		sbi->sbi_vcomm = NULL;
 		sbi->sbi_root = NULL;
-	}
-	if ( vc ) {
-		vc->vc_sb = NULL;
-		vc->vc_inuse = 0;
+		sbi->sbi_sb = NULL;
 	}
         if (root) {
                 iput(root);
@@ -166,7 +149,7 @@
 	coda_cache_clear_all(sb);
 	sb_info = coda_sbp(sb);
 	sb_info->sbi_vcomm->vc_inuse = 0;
-	sb_info->sbi_vcomm->vc_sb = NULL;
+	coda_super_info.sbi_sb = NULL;
 	printk("Coda: Bye bye.\n");
 	memset(sb_info, 0, sizeof(* sb_info));
 
@@ -288,80 +271,5 @@
 	return register_filesystem(&coda_fs_type);
 }
 
-/* MODULE stuff is in psdev.c */
-
-/*  helpers */
-static struct vcomm *coda_psinode2vcomm(struct inode *inode) 
-{
-        
-	unsigned int minor = MINOR(inode->i_rdev);
-	CDEBUG(D_PSDEV,"minor %d\n", minor);
-	if ( minor < MAX_CODADEVS ) 
-	      return &(psdev_vcomm[minor]);
-	else
-	      return NULL;
-}
-
-static struct coda_sb_info *coda_psinode2sbi(struct inode *inode) 
-{
-	unsigned int minor = MINOR(inode->i_rdev);
-
-	CDEBUG(D_PSDEV,"minor %d\n", minor);
-	if ( (minor >= 0) && (minor < MAX_CODADEVS)) 
-	        return &(coda_super_info[minor]);
-	else
-	        return NULL;
-}
-
-/* name lookup for psdev passed in by mount */
-static int coda_get_psdev(void *data, struct inode **res_dev)
-{
-        char **psdev_path;
-        struct inode *psdev = 0;
-	struct dentry *ent=NULL;
-
- 
-	if ( ! data ) { 
-		printk("coda_get_psdev: no data!\n");
-		return 1;
-	} 
-
-	psdev_path = data;
-        ent = namei((char *) *psdev_path);
-        if (IS_ERR(ent)) {
-		printk("namei error %ld for %d\n", PTR_ERR(ent), 
-		       (int) psdev_path);
-		return 1;
-        }
-	psdev = ent->d_inode;
-
-        if (!S_ISCHR(psdev->i_mode)) {
-		printk("not a character device\n");
-		return 1;
-        }
-	CDEBUG(D_PSDEV,"major %d, minor %d, count %d\n", 
-	       MAJOR(psdev->i_rdev), 
-	       MINOR(psdev->i_rdev), psdev->i_count);
-        
-        if (MAJOR(psdev->i_rdev) != CODA_PSDEV_MAJOR) {
-		printk("device %d not a Coda PSDEV device\n", 
-		       MAJOR(psdev->i_rdev));
-		return 1;
-        }
 
-        if (MINOR(psdev->i_rdev) >= MAX_CODADEVS) { 
-		printk("minor %d not an allocated Coda PSDEV\n", 
-		       psdev->i_rdev);
-		return 1;
-        }
 
-        if (psdev->i_count < 1) {
-		printk("coda device minor %d not open (i_count = %d)\n", 
-		       MINOR(psdev->i_rdev), psdev->i_count);
-		return 1;
-        }
-        
-        *res_dev = psdev;
-	EXIT;  
-        return 0;
-}
diff -u --recursive --new-file v2.1.131/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.1.131/linux/fs/coda/psdev.c	Sat Sep  5 16:46:41 1998
+++ linux/fs/coda/psdev.c	Fri Dec 18 14:09:17 1998
@@ -17,7 +17,6 @@
  *              Copyright (c) 1997 Carnegie-Mellon University
  */
 
-#include <linux/config.h> /* for CONFIG_PROC_FS */
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
@@ -34,6 +33,7 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <asm/system.h>
@@ -47,85 +47,30 @@
 #include <linux/coda_cache.h>
 #include <linux/coda_proc.h>
 
-extern struct proc_dir_entry proc_sys_root;
-
 /* 
  * Coda stuff
  */
 extern struct file_system_type coda_fs_type;
 extern int init_coda_fs(void);
-extern int cfsnc_get_info(char *buffer, char **start, off_t offset, int length, int dummy);
-extern int cfsnc_nc_info(char *buffer, char **start, off_t offset, int length, int dummy);
 
 /* statistics */
-struct coda_upcallstats coda_callstats;
-int           coda_hard = 0;  /* allows signals during upcalls */
+int           coda_hard    = 0;  /* allows signals during upcalls */
 unsigned long coda_timeout = 30; /* .. secs, then signals will dequeue */
-extern struct coda_sb_info coda_super_info[MAX_CODADEVS];
-struct vcomm psdev_vcomm[MAX_CODADEVS];
-
-/* queue stuff for the messages */
-static inline void init_queue(struct queue *head)
-{
-	head->forw = head;
-	head->back = head;
-}
-
-static inline struct vmsg *q_getnext(struct queue *elt)
-{
-	return (struct vmsg *)(elt->forw);
-}
-
-static inline int q_end(struct vmsg *msg, struct queue *queue)
-{
-	return (struct queue *)msg == queue;
-}
-
-static inline int q_empty(struct queue *queue)
-{
-	return queue->forw == queue;
-}
-
-/* insert before head, ie. at the tail */
-void coda_q_insert(struct queue *el, struct queue *head)
-{
-	el->forw = head->back->forw;
-	el->back = head->back;
-	head->back->forw = el;
-	head->back = el;
-}
-
-void coda_q_remove(struct queue *el)
-{
-	el->forw->back = el->back;
-	el->back->forw = el->forw;
-}
-
-static struct vcomm *coda_psdev2vcomm(struct file *file)
-{
-       	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
-	struct vcomm *vcp = NULL;
 
-	if ( (minor >= 0)  && (minor < MAX_CODADEVS) )
-	        vcp = &psdev_vcomm[minor];
-	return vcp;
-}
+struct coda_sb_info coda_super_info;
+struct venus_comm coda_upc_comm;
 	
 /*
  * Device operations
  */
 
-
 static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
 {
-        struct vcomm *vcp = coda_psdev2vcomm(file);
+        struct venus_comm *vcp = &coda_upc_comm;
 	unsigned int mask = POLLOUT | POLLWRNORM;
 
-	if ( !vcp ) 
-	        return -ENXIO;
-
 	poll_wait(file, &(vcp->vc_waitq), wait);
-	if (!q_empty(&(vcp->vc_pending)))
+	if (!list_empty(&vcp->vc_pending))
                 mask |= POLLIN | POLLRDNORM;
 
 	return mask;
@@ -139,54 +84,51 @@
 static ssize_t coda_psdev_write(struct file *file, const char *buf, 
 				size_t count, loff_t *off)
 {
-        struct vcomm *vcp = coda_psdev2vcomm(file);
-        struct vmsg *vmp;
-	int error = 0;
-	int size;
-        u_long uniq;
-        u_long opcode;
-        u_long opcodebuf[2];
-        
-        if (!vcp)
-                return -ENXIO;
+        struct venus_comm *vcp = &coda_upc_comm;
+        struct upc_req *req = NULL;
+        struct upc_req *tmp;
+	struct list_head *lh;
+	struct coda_in_hdr hdr;
+	int error;
 
+
+	if ( !coda_upc_comm.vc_pid ) 
+		return -EIO;
         /* Peek at the opcode, uniquefier */
-	if (copy_from_user(opcodebuf, buf, 2 * sizeof(u_long)))
+	if (copy_from_user(&hdr, buf, 2 * sizeof(u_long)))
 	        return -EFAULT;
-	opcode = opcodebuf[0];
-        uniq = opcodebuf[1];
 
-	CDEBUG(D_PSDEV, "(process,opc,uniq)=(%d,%ld,%ld)\n", 
-	       current->pid, opcode, uniq);
+	CDEBUG(D_PSDEV, "(process,opc,uniq)=(%d,%ld,%ld), count %d\n", 
+	       current->pid, hdr.opcode, hdr.unique, count);
 
-        if (DOWNCALL(opcode)) {
+        if (DOWNCALL(hdr.opcode)) {
 		struct super_block *sb = NULL;
                 union outputArgs *dcbuf;
-		size = sizeof(*dcbuf);
+		int size = sizeof(*dcbuf);
 
-		sb = vcp->vc_sb;
+		sb = coda_super_info.sbi_sb;
 		if ( !sb ) {
 			printk("coda_psdev_write: downcall, no SB!\n");
 			return count;
 		}
 		CDEBUG(D_PSDEV, "handling downcall\n");
 
-		if  ( count < sizeof(struct cfs_out_hdr) ) {
+		if  ( count < sizeof(struct coda_out_hdr) ) {
 		        printk("coda_downcall opc %ld uniq %ld, not enough!\n",
-			       opcode, uniq);
+			       hdr.opcode, hdr.unique);
 			return count;
 		}
 		CODA_ALLOC(dcbuf, union outputArgs *, size);
 		if ( count > size ) {
 		        printk("Coda: downcall opc %ld, uniq %ld, too much!",
-			       opcode, uniq);
+			       hdr.opcode, hdr.unique);
 		        count = size;
 		}
 		if (copy_from_user(dcbuf, buf, count))
 		        return -EFAULT;
 
 		/* what downcall errors does Venus handle ? */
-		error = coda_downcall(opcode, dcbuf, sb);
+		error = coda_downcall(hdr.opcode, dcbuf, sb);
 
 		if ( error) {
 		        printk("psdev_write: coda_downcall error: %d\n", 
@@ -199,41 +141,41 @@
 
         
         /* Look for the message on the processing queue. */
-        for (vmp = q_getnext(&(vcp->vc_processing));
-	     !q_end(vmp, &(vcp->vc_processing));
-             vmp = q_getnext(&(vmp->vm_chain))) {
-	        if (vmp->vm_unique == uniq) {
+	lh  = &vcp->vc_processing;
+        while ( (lh = lh->next) != &vcp->vc_processing ) {
+		tmp = list_entry(lh, struct upc_req , uc_chain);
+	        if (tmp->uc_unique == hdr.unique) {
+			req = tmp;
+			list_del(&req->uc_chain);
+			CDEBUG(D_PSDEV,"Eureka: uniq %ld on queue!\n", 
+			       hdr.unique);
 			break;
-			CDEBUG(D_PSDEV,"Eureka: uniq %ld on queue!\n", uniq);
 		}
 	}
-        if (q_end(vmp, &(vcp->vc_processing))) {
+        if (!req) {
 	        printk("psdev_write: msg (%ld, %ld) not found\n", 
-		       opcode, uniq);
+		       hdr.opcode, hdr.unique);
 		return(-ESRCH);
         }
 
-        /* Remove the message from the processing queue */
-        coda_q_remove(&(vmp->vm_chain));
-
         /* move data into response buffer. */
-        if (vmp->vm_outSize < count) {
+        if (req->uc_outSize < count) {
                 printk("psdev_write: too much cnt: %d, cnt: %d, opc: %ld, uniq: %ld.\n",
-		       vmp->vm_outSize, count, opcode, uniq);
-		count = vmp->vm_outSize; /* don't have more space! */
+		       req->uc_outSize, count, hdr.opcode, hdr.unique);
+		count = req->uc_outSize; /* don't have more space! */
 	}
-        if (copy_from_user(vmp->vm_data, buf, count))
+        if (copy_from_user(req->uc_data, buf, count))
 	        return -EFAULT;
 
 	/* adjust outsize. is this usefull ?? */
-        vmp->vm_outSize = count;	
-        vmp->vm_flags |= VM_WRITE;
+        req->uc_outSize = count;	
+        req->uc_flags |= REQ_WRITE;
 
 	CDEBUG(D_PSDEV, 
-	       "Found! Count %d for (opc,uniq)=(%ld,%ld), vmsg at %x\n", 
-	        count, opcode, uniq, (int)&vmp);
+	       "Found! Count %d for (opc,uniq)=(%ld,%ld), upc_req at %x\n", 
+	        count, hdr.opcode, hdr.unique, (int)&req);
 
-        wake_up(&vmp->vm_sleep);
+        wake_up(&req->uc_sleep);
         return(count);  
 }
 
@@ -244,47 +186,41 @@
 static ssize_t coda_psdev_read(struct file * file, char * buf, 
 			       size_t count, loff_t *off)
 {
-        struct vcomm *vcp = coda_psdev2vcomm(file);
-        struct vmsg *vmp;
+        struct venus_comm *vcp = &coda_upc_comm;
+        struct upc_req *req;
 	int result = count ;
 
-        if (!vcp)
-              return -ENXIO;
-        
-        /* Get message at head of request queue. */
-        if (q_empty(&(vcp->vc_pending))) {
-              return 0;	
+        CDEBUG(D_PSDEV, "count %d\n", count);
+        if (list_empty(&(vcp->vc_pending))) {
+              return -1;	
         }
     
-        vmp = q_getnext(&(vcp->vc_pending));
-        coda_q_remove(&(vmp->vm_chain));
+        req = list_entry((vcp->vc_pending.next), struct upc_req, uc_chain);
+        list_del(&(req->uc_chain));
 
         /* Move the input args into userspace */
-        if (vmp->vm_inSize <= count)
-              result = vmp->vm_inSize;
+        if (req->uc_inSize <= count)
+              result = req->uc_inSize;
 
-        if (count < vmp->vm_inSize) {
+        if (count < req->uc_inSize) {
                 printk ("psdev_read: Venus read %d bytes of %d in message\n",
-			count, vmp->vm_inSize);
+			count, req->uc_inSize);
         }
 
-        if ( copy_to_user(buf, vmp->vm_data, result))
+        if ( copy_to_user(buf, req->uc_data, result))
 	        return -EFAULT;
         
-        if (vmp->vm_chain.forw == 0 || vmp->vm_chain.back == 0)
-                printk("coda_psdev_read: bad chain");
-
         /* If request was a signal, don't enqueue */
-        if (vmp->vm_opcode == CFS_SIGNAL) {
+        if (req->uc_opcode == CODA_SIGNAL) {
                     CDEBUG(D_PSDEV, "vcread: signal msg (%d, %d)\n", 
-                              vmp->vm_opcode, vmp->vm_unique);
-              CODA_FREE(vmp->vm_data, sizeof(struct cfs_in_hdr));
-              CODA_FREE(vmp, sizeof(struct vmsg));
+                              req->uc_opcode, req->uc_unique);
+              CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
+              CODA_FREE(req, sizeof(struct upc_req));
               return count;
         }
     
-        vmp->vm_flags |= VM_READ;
-        coda_q_insert(&(vmp->vm_chain), &(vcp->vc_processing));
+        req->uc_flags |= REQ_READ;
+        list_add(&(req->uc_chain), vcp->vc_processing.prev);
 
         return result;
 }
@@ -292,85 +228,87 @@
 
 static int coda_psdev_open(struct inode * inode, struct file * file)
 {
-        register struct vcomm *vcp = NULL;
+        struct venus_comm *vcp = &coda_upc_comm;
         ENTRY;
-        
-	vcp =coda_psdev2vcomm(file);
-
-        if (!vcp)
-		return -ENODEV;
+	
+	/* first opener: must be lento. Initialize & take its pid */
+	if ( file->f_flags == O_RDWR ) {
+		if ( vcp->vc_pid ) {
+			printk("Venus pid already set to %d!!\n", vcp->vc_pid);
+			return -1;
+		}
+		if ( vcp->vc_inuse ) {
+			printk("psdev_open: Cannot O_RDWR while open.\n");
+			return -1;
+		}
+	}
+	
+	vcp->vc_inuse++;
+	MOD_INC_USE_COUNT;
 
-	if (vcp->vc_inuse)
-		return -EBUSY;
 
-	memset(vcp, 0, sizeof(struct vcomm));
-	vcp->vc_inuse = 1;
-	MOD_INC_USE_COUNT;
+	if ( file->f_flags == O_RDWR ) {
+		vcp->vc_pid = current->pid;
+		vcp->vc_seq = 0;
+		INIT_LIST_HEAD(&vcp->vc_pending);
+		INIT_LIST_HEAD(&vcp->vc_processing);
+	}
 
-        init_queue(&(vcp->vc_pending));
-        init_queue(&(vcp->vc_processing));
+	CDEBUG(D_PSDEV, "inuse: %d, vc_pid %d, caller %d\n",
+	       vcp->vc_inuse, vcp->vc_pid, current->pid);
 
-	memset(&coda_callstats, 0, sizeof(struct coda_upcallstats));
 	EXIT;
         return 0;
 }
 
 
-static int
-coda_psdev_release(struct inode * inode, struct file * file)
+
+static int coda_psdev_release(struct inode * inode, struct file * file)
 {
-        struct vcomm *vcp;
-        struct vmsg *vmp;
-	unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
+        struct venus_comm *vcp = &coda_upc_comm;
+        struct upc_req *req;
+	struct list_head *lh, *next;
 	ENTRY;
 
-        vcp = coda_psdev2vcomm(file);
+	if ( !vcp->vc_inuse ) {
+		printk("psdev_release: Not open.\n");
+		return -1;
+	}
+
+	vcp->vc_inuse--;
+	MOD_DEC_USE_COUNT;
+	CDEBUG(D_PSDEV, "inuse: %d, vc_pid %d, caller %d\n",
+	       vcp->vc_inuse, vcp->vc_pid, current->pid);
+
+	if ( vcp->vc_pid != current->pid ) {
+		return 0;
+	}
         
-        if ( !vcp || !vcomm_open(vcp) ) {
-              printk("psdev_release: not open");
-              return 0;
-        }
-    
-	
-	/* flush the name cache so that we can unmount */
-	CDEBUG(D_PSDEV, "Flushing the cache.\n");
-	/* cfsnc_flush(); */
-	/* cfsnc_use = 0; */
-	CDEBUG(D_PSDEV, "Done.\n");
-	
-	/* if operations are in progress perhaps the kernel
-	   can profit from setting the C_DYING flag on the root 
-	   cnode of Coda filesystems */
-        if (coda_super_info[minor].sbi_root) {
-                struct coda_inode_info *cnp = 
-			ITOC(coda_super_info[minor].sbi_root);
-                cnp->c_flags |= C_DYING;
-        } else 
-		vcp->vc_inuse = 0;	
-	
-    
+	vcp->vc_pid = 0;
         /* Wakeup clients so they can return. */
-        for (vmp = q_getnext(&(vcp->vc_pending));
-             !q_end(vmp, &(vcp->vc_pending));
-             vmp = q_getnext(&(vmp->vm_chain))) {	    
-              /* Free signal request messages and don't wakeup cause
-                 no one is waiting. */
-              if (vmp->vm_opcode == CFS_SIGNAL) {
-                    CODA_FREE(vmp->vm_data, sizeof(struct cfs_in_hdr));
-                    CODA_FREE(vmp, (u_int)sizeof(struct vmsg));
-                    continue;
-              }
-              wake_up(&vmp->vm_sleep);
+	CDEBUG(D_PSDEV, "wake up pending clients\n");
+	lh = vcp->vc_pending.next;
+	next = lh;
+	while ( (lh = next) != &vcp->vc_pending) {
+		next = lh->next;
+		req = list_entry(lh, struct upc_req, uc_chain);
+		/* Async requests need to be freed here */
+		if (req->uc_flags & REQ_ASYNC) {
+			CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
+			CODA_FREE(req, (u_int)sizeof(struct upc_req));
+			continue;
+		}
+		wake_up(&req->uc_sleep);
         }
         
-        for (vmp = q_getnext(&(vcp->vc_processing));
-             !q_end(vmp, &(vcp->vc_processing));
-             vmp = q_getnext(&(vmp->vm_chain))) {
-	        wake_up(&vmp->vm_sleep);
+	lh = &vcp->vc_processing;
+	CDEBUG(D_PSDEV, "wake up processing clients\n");
+	while ( (lh = lh->next) != &vcp->vc_processing) {
+		req = list_entry(lh, struct upc_req, uc_chain);
+	        wake_up(&req->uc_sleep);
         }
-        
-        mark_vcomm_closed(vcp);
-	MOD_DEC_USE_COUNT;
+	CDEBUG(D_PSDEV, "Done.\n");
+
 	EXIT;
 	return 0;
 }
@@ -395,94 +333,6 @@
 };
 
 
-#ifdef CONFIG_PROC_FS
-
-
-struct proc_dir_entry proc_sys_coda = {
-        0, 4, "coda",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL,
-	NULL, NULL
-};
-
-/*
- target directory structure:
-   /proc/fs  (see linux/fs/proc/root.c)
-   /proc/fs/coda
-   /proc/fs/coda/{vfs_stats,
-
-*/
-
-
-struct proc_dir_entry proc_fs_coda = {
-        PROC_FS_CODA, 4, "coda",
-        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
-        0, &proc_dir_inode_operations,
-	NULL, NULL,
-	NULL,
-	NULL, NULL
-};
-
-struct proc_dir_entry proc_coda_vfs =  {
-                PROC_VFS_STATS , 9, "vfs_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_vfs_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_vfs_control =  {
-                0 , 9, "vfs_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_vfs_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_upcall =  {
-                PROC_UPCALL_STATS , 12, "upcall_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_upcall_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_upcall_control =  {
-                0 , 12, "upcall_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_upcall_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_permission =  {
-                PROC_PERMISSION_STATS , 16, "permission_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_permission_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_permission_control =  {
-                0 , 16, "permission_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_permission_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_cache_inv =  {
-                PROC_CACHE_INV_STATS , 15, "cache_inv_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_cache_inv_stats_get_info
-        };
-
-struct proc_dir_entry proc_coda_cache_inv_control =  {
-                0 , 15, "cache_inv_stats",
-                S_IFREG | S_IRUGO, 1, 0, 0,
-                0, &proc_net_inode_operations,
-                coda_cache_inv_stats_get_info
-        };
-
-#endif
-
 
 __initfunc(int init_coda(void)) 
 {
@@ -509,32 +359,11 @@
 		     CODA_PSDEV_MAJOR);
               return -EIO;
 	}
-	memset(psdev_vcomm, 0, sizeof(psdev_vcomm));
-	memset(coda_super_info, 0, sizeof(coda_super_info));
-	memset(&coda_callstats, 0, sizeof(coda_callstats));
-
-	reset_coda_vfs_stats();
-	reset_coda_upcall_stats();
-	reset_coda_permission_stats();
-	reset_coda_cache_inv_stats();
-
-#ifdef CONFIG_PROC_FS
-	proc_register(&proc_root_fs,&proc_fs_coda);
-	proc_register(&proc_fs_coda,&proc_coda_vfs);
-	proc_register(&proc_fs_coda,&proc_coda_upcall);
-	proc_register(&proc_fs_coda,&proc_coda_permission);
-	proc_register(&proc_fs_coda,&proc_coda_cache_inv);
-#endif
-
-#ifdef CONFIG_SYSCTL
-	proc_register(&proc_sys_root,&proc_sys_coda);
-	proc_register(&proc_sys_coda,&proc_coda_vfs_control);
-	proc_register(&proc_sys_coda,&proc_coda_upcall_control);
-	proc_register(&proc_sys_coda,&proc_coda_permission_control);
-	proc_register(&proc_sys_coda,&proc_coda_cache_inv_control);
+	memset(&coda_upc_comm, 0, sizeof(coda_upc_comm));
+	memset(&coda_super_info, 0, sizeof(coda_super_info));
 
 	coda_sysctl_init();
-#endif 
+
 	return 0;
 }
 
@@ -546,7 +375,7 @@
 int init_module(void)
 {
 	int status;
-	printk(KERN_INFO "Coda Kernel/Venus communications (module), v4.7.1, braam@cs.cmu.edu.\n");
+	printk(KERN_INFO "Coda Kernel/Venus communications (module), v4.7.5, braam@cs.cmu.edu.\n");
 
 	status = init_coda_psdev();
 	if ( status ) {
@@ -572,24 +401,7 @@
                 printk("coda: failed to unregister filesystem\n");
         }
         unregister_chrdev(CODA_PSDEV_MAJOR,"coda_psdev");
-
-#if CONFIG_PROC_FS
-        coda_sysctl_clean();
-
-        proc_unregister(&proc_sys_coda, proc_coda_cache_inv_control.low_ino);
-        proc_unregister(&proc_sys_coda, proc_coda_permission_control.low_ino);
-        proc_unregister(&proc_sys_coda, proc_coda_upcall_control.low_ino);
-	proc_unregister(&proc_sys_coda, proc_coda_vfs_control.low_ino);
-	proc_unregister(&proc_sys_root, proc_sys_coda.low_ino);
-#endif
-
-#ifdef CONFIG_SYSCTL
-        proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino);
-        proc_unregister(&proc_fs_coda, proc_coda_vfs.low_ino);
-	proc_unregister(&proc_root_fs, proc_fs_coda.low_ino);
-#endif 
+	coda_sysctl_clean();
 }
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/fs/coda/stats.c linux/fs/coda/stats.c
--- v2.1.131/linux/fs/coda/stats.c	Wed Jul  1 19:38:55 1998
+++ linux/fs/coda/stats.c	Fri Dec 18 12:45:00 1998
@@ -30,7 +30,7 @@
 struct coda_vfs_stats		coda_vfs_stat;
 struct coda_permission_stats	coda_permission_stat;
 struct coda_cache_inv_stats	coda_cache_inv_stat;
-struct coda_upcall_stats_entry coda_upcall_stat[CFS_NCALLS];
+struct coda_upcall_stats_entry coda_upcall_stat[CODA_NCALLS];
 
 /* keep this in sync with coda.h! */
 char *coda_upcall_names[] = {
@@ -122,7 +122,7 @@
 {
 	struct coda_upcall_stats_entry * pentry;
 	
-	if ( opcode < 0 || opcode > CFS_NCALLS - 1) {
+	if ( opcode < 0 || opcode > CODA_NCALLS - 1) {
 		printk("Nasty opcode %d passed to coda_upcall_stats\n",
 		       opcode);
 		return;
@@ -321,7 +321,7 @@
 	if ( offset < 320) 
 		len += sprintf( buffer + len,"%-79s\n",	"------\t\t    -----\t------------\t-----------------");
 	pos = 320; 
-	for ( i = 0 ; i < CFS_NCALLS ; i++ ) {
+	for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
 		tmplen += sprintf(tmpbuf,"%s\t%9d\t%10ld\t%10ld", 
 				  coda_upcall_names[i],
 				  coda_upcall_stat[i].count, 
diff -u --recursive --new-file v2.1.131/linux/fs/coda/symlink.c linux/fs/coda/symlink.c
--- v2.1.131/linux/fs/coda/symlink.c	Mon Sep 28 10:51:34 1998
+++ linux/fs/coda/symlink.c	Fri Dec 18 12:45:00 1998
@@ -26,7 +26,8 @@
 #include <linux/coda_proc.h>
 
 static int coda_readlink(struct dentry *de, char *buffer, int length);
-static struct dentry *coda_follow_link(struct dentry *, struct dentry *, unsigned int);
+static struct dentry *coda_follow_link(struct dentry *, struct dentry *, 
+				       unsigned int);
 
 struct inode_operations coda_symlink_inode_operations = {
 	NULL,			/* no file-operations */
@@ -64,8 +65,8 @@
 	coda_vfs_stat.readlink++;
 
         /* the maximum length we receive is len */
-        if ( length > CFS_MAXPATHLEN ) 
-	        len = CFS_MAXPATHLEN;
+        if ( length > CODA_MAXPATHLEN ) 
+	        len = CODA_MAXPATHLEN;
 	else
 	        len = length;
 	CODA_ALLOC(buf, char *, len);
@@ -85,15 +86,14 @@
 	return error;
 }
 
-static struct dentry *coda_follow_link(struct dentry *de, 
-				       struct dentry *base,
+static struct dentry *coda_follow_link(struct dentry *de, struct dentry *base,
 				       unsigned int follow)
 {
 	struct inode *inode = de->d_inode;
 	int error;
 	struct coda_inode_info *cnp;
 	unsigned int len;
-	char mem[CFS_MAXPATHLEN];
+	char mem[CODA_MAXPATHLEN];
 	char *path;
 	ENTRY;
 	CDEBUG(D_INODE, "(%x/%ld)\n", inode->i_dev, inode->i_ino);
@@ -101,7 +101,7 @@
         cnp = ITOC(inode);
 	coda_vfs_stat.follow_link++;
 
-	len = CFS_MAXPATHLEN;
+	len = CODA_MAXPATHLEN;
 	error = venus_readlink(inode->i_sb, &(cnp->c_fid), mem, &len);
 
 	if (error) {
diff -u --recursive --new-file v2.1.131/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.1.131/linux/fs/coda/sysctl.c	Thu May  7 22:51:53 1998
+++ linux/fs/coda/sysctl.c	Fri Dec 18 14:09:31 1998
@@ -5,9 +5,13 @@
  * 
  * Carnegie Mellon encourages users to contribute improvements to
  * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
+ * 
+ * CODA operation statistics
+ * (c) March, 1998 Zhanyong Wan <zhanyong.wan@yale.edu>
+ *
  */
-/* sysctl entries for Coda! */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/sysctl.h>
@@ -27,19 +31,9 @@
 #include <linux/coda_psdev.h>
 #include <linux/coda_cache.h>
 #include <linux/coda_proc.h>
-extern int coda_debug;
-/* extern int cfsnc_use; */
-extern int coda_print_entry;
-/* extern int cfsnc_flushme; */
-extern int cfsnc_procsize;
-/* extern void cfsnc_flush(void); */
-void coda_sysctl_init(void);
-void coda_sysctl_clean(void);
 
-int coda_dointvec(ctl_table *table, int write, struct file *filp,
-                  void *buffer, size_t *lenp);
+static struct ctl_table_header *fs_table_header;
 
-struct ctl_table_header *fs_table_header, *coda_table_header;
 #define FS_CODA         1       /* Coda file system */
 
 #define CODA_DEBUG  	 1	 /* control debugging */
@@ -52,14 +46,12 @@
 #define CODA_PERMISSION	 8       /* permission statistics */
 #define CODA_CACHE_INV 	 9       /* cache invalidation statistics */
 
-
-
 static ctl_table coda_table[] = {
-	{CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &coda_dointvec},
-	{CODA_ENTRY, "printentry", &coda_print_entry, sizeof(int), 0644, NULL, &coda_dointvec},
- 	{CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &coda_dointvec}, 
- 	{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &coda_dointvec},
- 	{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &coda_dointvec},
+	{CODA_DEBUG, "debug", &coda_debug, sizeof(int), 0644, NULL, &proc_dointvec},
+	{CODA_ENTRY, "printentry", &coda_print_entry, sizeof(int), 0644, NULL, &proc_dointvec},
+ 	{CODA_MC, "accesscache", &coda_access_cache, sizeof(int), 0644, NULL, &proc_dointvec}, 
+ 	{CODA_TIMEOUT, "timeout", &coda_timeout, sizeof(int), 0644, NULL, &proc_dointvec},
+ 	{CODA_HARD, "hard", &coda_hard, sizeof(int), 0644, NULL, &proc_dointvec},
  	{CODA_VFS, "vfs_stats", NULL, 0, 0644, NULL, &do_reset_coda_vfs_stats},
  	{CODA_UPCALL, "upcall_stats", NULL, 0, 0644, NULL, &do_reset_coda_upcall_stats},
  	{CODA_PERMISSION, "permission_stats", NULL, 0, 0644, NULL, &do_reset_coda_permission_stats},
@@ -67,114 +59,478 @@
 	{ 0 }
 };
 
-
 static ctl_table fs_table[] = {
        {FS_CODA, "coda",    NULL, 0, 0555, coda_table},
        {0}
 };
 
+struct coda_vfs_stats		coda_vfs_stat;
+struct coda_permission_stats	coda_permission_stat;
+struct coda_cache_inv_stats	coda_cache_inv_stat;
+struct coda_upcall_stats_entry  coda_upcall_stat[CODA_NCALLS];
+struct coda_upcallstats         coda_callstats;
+
+/* keep this in sync with coda.h! */
+char *coda_upcall_names[] = {
+	"totals      ",   /*  0 */
+	"noop        ",   /*  1 */
+	"root        ",   /*  2 */
+	"sync        ",   /*  3 */
+	"open        ",   /*  4 */
+	"close       ",   /*  5 */
+	"ioctl       ",   /*  6 */
+	"getattr     ",   /*  7 */
+	"setattr     ",   /*  8 */
+	"access      ",   /*  9 */
+	"lookup      ",   /* 10 */
+	"create      ",   /* 11 */
+	"remove      ",   /* 12 */
+	"link        ",   /* 13 */
+	"rename      ",   /* 14 */
+	"mkdir       ",   /* 15 */
+	"rmdir       ",   /* 16 */
+	"readdir     ",   /* 17 */
+	"symlink     ",   /* 18 */
+	"readlink    ",   /* 19 */
+	"fsync       ",   /* 20 */
+	"inactive    ",   /* 21 */
+	"vget        ",   /* 22 */
+	"signal      ",   /* 23 */
+	"replace     ",   /* 24 */
+	"flush       ",   /* 25 */
+	"purgeuser   ",   /* 26 */
+	"zapfile     ",   /* 27 */
+	"zapdir      ",   /* 28 */
+	"zapvnode    ",   /* 28 */
+	"purgefid    ",   /* 30 */
+	"open_by_path"    /* 31 */
+};
 
 
-void coda_sysctl_init()
+void reset_coda_vfs_stats( void )
+{
+	memset( &coda_vfs_stat, 0, sizeof( coda_vfs_stat ) );
+}
+
+void reset_coda_upcall_stats( void )
+{
+	memset( &coda_upcall_stat, 0, sizeof( coda_upcall_stat ) );
+}
+
+void reset_coda_permission_stats( void )
+{
+	memset( &coda_permission_stat, 0, sizeof( coda_permission_stat ) );
+}
+
+void reset_coda_cache_inv_stats( void )
+{
+	memset( &coda_cache_inv_stat, 0, sizeof( coda_cache_inv_stat ) );
+}
+
+
+void do_time_stats( struct coda_upcall_stats_entry * pentry, 
+		    unsigned long runtime )
+{
+	
+	unsigned long time = runtime * 1000 /HZ;	/* time in ms */
+	CDEBUG(D_SPECIAL, "time: %ld\n", time);
+
+	if ( pentry->count == 0 ) {
+		pentry->time_sum = pentry->time_squared_sum = 0;
+	}
+	
+	pentry->count++;
+	pentry->time_sum += time;
+	pentry->time_squared_sum += time*time;
+}
+
+
+
+void coda_upcall_stats(int opcode, long unsigned runtime) 
+{
+	struct coda_upcall_stats_entry * pentry;
+	
+	if ( opcode < 0 || opcode > CODA_NCALLS - 1) {
+		printk("Nasty opcode %d passed to coda_upcall_stats\n",
+		       opcode);
+		return;
+	}
+		
+	pentry = &coda_upcall_stat[opcode];
+	do_time_stats(pentry, runtime);
+
+        /* fill in the totals */
+	pentry = &coda_upcall_stat[0];
+	do_time_stats(pentry, runtime);
+
+}
+
+unsigned long get_time_average( const struct coda_upcall_stats_entry * pentry )
+{
+	return ( pentry->count == 0 ) ? 0 : pentry->time_sum / pentry->count;
+}
+
+static inline unsigned long absolute( unsigned long x )
+{
+	return x >= 0 ? x : -x;
+}
+
+static unsigned long sqr_root( unsigned long x )
+{
+	unsigned long y = x, r;
+	int n_bit = 0;
+  
+	if ( x == 0 )
+		return 0;
+	if ( x < 0)
+		x = -x;
+
+	while ( y ) {
+		y >>= 1;
+		n_bit++;
+	}
+  
+	r = 1 << (n_bit/2);
+  
+	while ( 1 ) {
+		r = (r + x/r)/2;
+		if ( r*r <= x && x < (r+1)*(r+1) )
+			break;
+	}
+  
+	return r;
+}
+
+unsigned long get_time_std_deviation( const struct coda_upcall_stats_entry * pentry )
+{
+	unsigned long time_avg;
+  
+	if ( pentry->count <= 1 )
+		return 0;
+  
+	time_avg = get_time_average( pentry );
+	return 
+	        sqr_root( (pentry->time_squared_sum / pentry->count) - 
+			    time_avg * time_avg );
+}
+
+int do_reset_coda_vfs_stats( ctl_table * table, int write, struct file * filp,
+			     void * buffer, size_t * lenp )
+{
+	if ( write ) {
+		reset_coda_vfs_stats();
+	}
+  
+	*lenp = 0;
+	return 0;
+}
+
+int do_reset_coda_upcall_stats( ctl_table * table, int write, 
+				struct file * filp, void * buffer, 
+				size_t * lenp )
 {
-	fs_table_header = register_sysctl_table(fs_table, 0);
-/*	coda_table_header = register_sysctl_table(coda_table, 0);*/
+	if ( write ) {
+		reset_coda_upcall_stats();
+	}
+  
+	*lenp = 0;
+	return 0;
 }
 
-void coda_sysctl_clean() {
-	/*unregister_sysctl_table(coda_table_header);*/
-	unregister_sysctl_table(fs_table_header);
-}
-
-int coda_dointvec(ctl_table *table, int write, struct file *filp,
-                  void *buffer, size_t *lenp)
-{
-        int *i, vleft, first=1, len, left, neg, val;
-        #define TMPBUFLEN 20
-        char buf[TMPBUFLEN], *p;
-        
-        if (!table->data || !table->maxlen || !*lenp ||
-            (filp->f_pos && !write)) {
-                *lenp = 0;
-                return 0;
-        }
-        
-        i = (int *) table->data;
-        vleft = table->maxlen / sizeof(int);
-        left = *lenp;
-        
-        for (; left && vleft--; i++, first=0) {
-                if (write) {
-		        while (left) {
-			        char c;
-				if(get_user(c,(char *) buffer))
-					return -EFAULT;
-				if (!isspace(c))
-					break;
-				left--;
-				((char *) buffer)++;
-			}
-                        if (!left)
-                                break;
-                        neg = 0;
-                        len = left;
-                        if (len > TMPBUFLEN-1)
-                                len = TMPBUFLEN-1;
-                        if (copy_from_user(buf, buffer, len))
-			        return -EFAULT;
-                        buf[len] = 0;
-                        p = buf;
-                        if (*p == '-' && left > 1) {
-                                neg = 1;
-                                left--, p++;
-                        }
-                        if (*p < '0' || *p > '9')
-                                break;
-                        val = simple_strtoul(p, &p, 0);
-                        len = p-buf;
-                        if ((len < left) && *p && !isspace(*p))
-                                break;
-                        if (neg)
-                                val = -val;
-                        buffer += len;
-                        left -= len;
-                        *i = val;
-                } else {
-                        p = buf;
-                        if (!first)
-                                *p++ = '\t';
-                        sprintf(p, "%d", *i);
-                        len = strlen(buf);
-                        if (len > left)
-                                len = left;
-                        if (copy_to_user(buffer, buf, len))
-			    return -EFAULT;
-                        left -= len;
-                        buffer += len;
-                }
-        }
-
-        if (!write && !first && left) {
-                if(put_user('\n', (char *) buffer))
-		        return -EFAULT;
-                left--, buffer++;
-        }
-        if (write) {
-                p = (char *) buffer;
-                while (left) {
-			char c;
-			if(get_user(c, p++))
-				return -EFAULT;
-			if (!isspace(c))
-				break;
-			left--;
-		}
-        }
-        if (write && first)
-                return -EINVAL;
-        *lenp -= left;
-        filp->f_pos += *lenp;
-        return 0;
+int do_reset_coda_permission_stats( ctl_table * table, int write, 
+				    struct file * filp, void * buffer, 
+				    size_t * lenp )
+{
+	if ( write ) {
+		reset_coda_permission_stats();
+	}
+  
+	*lenp = 0;
+	return 0;
 }
 
+int do_reset_coda_cache_inv_stats( ctl_table * table, int write, 
+				   struct file * filp, void * buffer, 
+				   size_t * lenp )
+{
+	if ( write ) {
+		reset_coda_cache_inv_stats();
+	}
+  
+	*lenp = 0;
+	return 0;
+}
+
+int coda_vfs_stats_get_info( char * buffer, char ** start, off_t offset,
+			     int length, int dummy )
+{
+	int len=0;
+	off_t begin;
+	struct coda_vfs_stats * ps = & coda_vfs_stat;
+  
+  /* this works as long as we are below 1024 characters! */
+	len += sprintf( buffer,
+			"Coda VFS statistics\n"
+			"===================\n\n"
+			"File Operations:\n"
+			"\tfile_read\t%9d\n"
+			"\tfile_write\t%9d\n"
+			"\tfile_mmap\t%9d\n"
+			"\topen\t\t%9d\n"
+			"\trelase\t\t%9d\n"
+			"\tfsync\t\t%9d\n\n"
+			"Dir Operations:\n"
+			"\treaddir\t\t%9d\n\n"
+			"Inode Operations\n"
+			"\tcreate\t\t%9d\n"
+			"\tlookup\t\t%9d\n"
+			"\tlink\t\t%9d\n"
+			"\tunlink\t\t%9d\n"
+			"\tsymlink\t\t%9d\n"
+			"\tmkdir\t\t%9d\n"
+			"\trmdir\t\t%9d\n"
+			"\trename\t\t%9d\n"
+			"\tpermission\t%9d\n"
+			"\treadpage\t%9d\n",
+
+			/* file operations */
+			ps->file_read,
+			ps->file_write,
+			ps->file_mmap,
+			ps->open,
+			ps->release,
+			ps->fsync,
+
+			/* dir operations */
+			ps->readdir,
+		  
+			/* inode operations */
+			ps->create,
+			ps->lookup,
+			ps->link,
+			ps->unlink,
+			ps->symlink,
+			ps->mkdir,
+			ps->rmdir,
+			ps->rename,
+			ps->permission,
+			ps->readpage );
+  
+	begin = offset;
+	*start = buffer + begin;
+	len -= begin;
+
+	if ( len > length )
+		len = length;
+	if ( len < 0 )
+		len = 0;
+
+	return len;
+}
+
+int coda_upcall_stats_get_info( char * buffer, char ** start, off_t offset,
+				int length, int dummy )
+{
+	int len=0;
+	int i;
+	off_t begin;
+	off_t pos = 0;
+	char tmpbuf[80];
+	int tmplen = 0;
+
+	ENTRY;
+	/* this works as long as we are below 1024 characters! */
+	if ( offset < 80 ) 
+		len += sprintf( buffer,"%-79s\n",	"Coda upcall statistics");
+	if ( offset < 160) 
+		len += sprintf( buffer + len,"%-79s\n",	"======================");
+	if ( offset < 240) 
+		len += sprintf( buffer + len,"%-79s\n",	"upcall\t\t    count\tavg time(ms)\tstd deviation(ms)");
+	if ( offset < 320) 
+		len += sprintf( buffer + len,"%-79s\n",	"------\t\t    -----\t------------\t-----------------");
+	pos = 320; 
+	for ( i = 0 ; i < CODA_NCALLS ; i++ ) {
+		tmplen += sprintf(tmpbuf,"%s\t%9d\t%10ld\t%10ld", 
+				  coda_upcall_names[i],
+				  coda_upcall_stat[i].count, 
+				  get_time_average(&coda_upcall_stat[i]),
+				  coda_upcall_stat[i].time_squared_sum);
+		pos += 80;
+		if ( pos < offset ) 
+			continue; 
+		len += sprintf(buffer + len, "%-79s\n", tmpbuf);
+		if ( len >= length ) 
+			break; 
+	}
+  
+	begin = len- (pos - offset);
+	*start = buffer + begin;
+	len -= begin;
+
+	if ( len > length )
+		len = length;
+	if ( len < 0 )
+		len = 0;
+	EXIT;
+	return len;
+}
+
+int coda_permission_stats_get_info( char * buffer, char ** start, off_t offset,
+				    int length, int dummy )
+{
+	int len=0;
+	off_t begin;
+	struct coda_permission_stats * ps = & coda_permission_stat;
+  
+	/* this works as long as we are below 1024 characters! */
+	len += sprintf( buffer,
+			"Coda permission statistics\n"
+			"==========================\n\n"
+			"count\t\t%9d\n"
+			"hit count\t%9d\n",
+
+			ps->count,
+			ps->hit_count );
+  
+	begin = offset;
+	*start = buffer + begin;
+	len -= begin;
+
+	if ( len > length )
+		len = length;
+	if ( len < 0 )
+		len = 0;
+
+	return len;
+}
 
+int coda_cache_inv_stats_get_info( char * buffer, char ** start, off_t offset,
+				   int length, int dummy )
+{
+	int len=0;
+	off_t begin;
+	struct coda_cache_inv_stats * ps = & coda_cache_inv_stat;
+  
+	/* this works as long as we are below 1024 characters! */
+	len += sprintf( buffer,
+			"Coda cache invalidation statistics\n"
+			"==================================\n\n"
+			"flush\t\t%9d\n"
+			"purge user\t%9d\n"
+			"zap_dir\t\t%9d\n"
+			"zap_file\t%9d\n"
+			"zap_vnode\t%9d\n"
+			"purge_fid\t%9d\n"
+			"replace\t\t%9d\n",
+			ps->flush,
+			ps->purge_user,
+			ps->zap_dir,
+			ps->zap_file,
+			ps->zap_vnode,
+			ps->purge_fid,
+			ps->replace );
+  
+	begin = offset;
+	*start = buffer + begin;
+	len -= begin;
+
+	if ( len > length )
+		len = length;
+	if ( len < 0 )
+		len = 0;
+
+	return len;
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ target directory structure:
+   /proc/fs  (see linux/fs/proc/root.c)
+   /proc/fs/coda
+   /proc/fs/coda/{vfs_stats,
+
+*/
+
+struct proc_dir_entry proc_fs_coda = {
+        PROC_FS_CODA, 4, "coda",
+        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+        0, &proc_dir_inode_operations,
+	NULL, NULL,
+	NULL,
+	NULL, NULL
+};
+
+struct proc_dir_entry proc_coda_vfs =  {
+                PROC_VFS_STATS , 9, "vfs_stats",
+                S_IFREG | S_IRUGO, 1, 0, 0,
+                0, &proc_net_inode_operations,
+                coda_vfs_stats_get_info
+        };
+
+struct proc_dir_entry proc_coda_upcall =  {
+                PROC_UPCALL_STATS , 12, "upcall_stats",
+                S_IFREG | S_IRUGO, 1, 0, 0,
+                0, &proc_net_inode_operations,
+                coda_upcall_stats_get_info
+        };
+
+struct proc_dir_entry proc_coda_permission =  {
+                PROC_PERMISSION_STATS , 16, "permission_stats",
+                S_IFREG | S_IRUGO, 1, 0, 0,
+                0, &proc_net_inode_operations,
+                coda_permission_stats_get_info
+        };
+
+
+struct proc_dir_entry proc_coda_cache_inv =  {
+                PROC_CACHE_INV_STATS , 15, "cache_inv_stats",
+                S_IFREG | S_IRUGO, 1, 0, 0,
+                0, &proc_net_inode_operations,
+                coda_cache_inv_stats_get_info
+        };
+
+#endif
+
+
+void coda_sysctl_init()
+{
+	memset(&coda_callstats, 0, sizeof(coda_callstats));
+	reset_coda_vfs_stats();
+	reset_coda_upcall_stats();
+	reset_coda_permission_stats();
+	reset_coda_cache_inv_stats();
+
+#ifdef CONFIG_PROC_FS
+	proc_register(&proc_root_fs,&proc_fs_coda);
+	proc_register(&proc_fs_coda,&proc_coda_vfs);
+	proc_register(&proc_fs_coda,&proc_coda_upcall);
+	proc_register(&proc_fs_coda,&proc_coda_permission);
+	proc_register(&proc_fs_coda,&proc_coda_cache_inv);
+#endif
+
+#ifdef CONFIG_SYSCTL
+	if ( !fs_table_header )
+		fs_table_header = register_sysctl_table(fs_table, 0);
+#endif 
+}
+
+void coda_sysctl_clean() 
+{
+
+#ifdef CONFIG_SYSCTL
+	if ( fs_table_header ) {
+		unregister_sysctl_table(fs_table_header);
+		fs_table_header = 0;
+	}
+#endif
+
+#if CONFIG_PROC_FS
+        proc_unregister(&proc_fs_coda, proc_coda_cache_inv.low_ino);
+        proc_unregister(&proc_fs_coda, proc_coda_permission.low_ino);
+        proc_unregister(&proc_fs_coda, proc_coda_upcall.low_ino);
+        proc_unregister(&proc_fs_coda, proc_coda_vfs.low_ino);
+	proc_unregister(&proc_root_fs, proc_fs_coda.low_ino);
+#endif 
+}
diff -u --recursive --new-file v2.1.131/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.1.131/linux/fs/coda/upcall.c	Sat Sep  5 16:46:41 1998
+++ linux/fs/coda/upcall.c	Fri Dec 18 12:45:00 1998
@@ -63,8 +63,8 @@
 		return b;
 }
 
-#define INSIZE(tag) sizeof(struct cfs_ ## tag ## _in)
-#define OUTSIZE(tag) sizeof(struct cfs_ ## tag ## _out)
+#define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)
+#define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)
 #define SIZE(tag)  max(INSIZE(tag), OUTSIZE(tag))
 
 
@@ -77,14 +77,14 @@
 	ENTRY;
 
         insize = SIZE(root);
-        UPARG(CFS_ROOT);
+        UPARG(CODA_ROOT);
 
 	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if (error) {
 	        printk("coda_get_rootfid: error %d\n", error);
 	} else {
-	        *fidp = (ViceFid) outp->cfs_root.VFid;
+	        *fidp = (ViceFid) outp->coda_root.VFid;
 		CDEBUG(D_SUPER, "VolumeId: %lx, VnodeId: %lx.\n",
 		       fidp->Volume, fidp->Vnode);
 	}
@@ -103,13 +103,13 @@
 	ENTRY;
 
         insize = SIZE(getattr); 
-	UPARG(CFS_GETATTR);
-        inp->cfs_getattr.VFid = *fid;
+	UPARG(CODA_GETATTR);
+        inp->coda_getattr.VFid = *fid;
 
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if ( !error )
-	        *attr = outp->cfs_getattr.attr;
+	        *attr = outp->coda_getattr.attr;
 
         if (inp) 
 		CODA_FREE(inp, insize);
@@ -125,10 +125,10 @@
         int insize, outsize, error;
 	
 	insize= SIZE(setattr);
-	UPARG(CFS_SETATTR);
+	UPARG(CODA_SETATTR);
 
-        inp->cfs_setattr.VFid = *fid;
-	inp->cfs_setattr.attr = *vattr;
+        inp->coda_setattr.VFid = *fid;
+	inp->coda_setattr.attr = *vattr;
 
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
@@ -148,10 +148,11 @@
 
 	offset = INSIZE(lookup);
         insize =  max(offset + length +1, OUTSIZE(lookup));
-	UPARG(CFS_LOOKUP);
+	UPARG(CODA_LOOKUP);
 
-        inp->cfs_lookup.VFid = *fid;
-	inp->cfs_lookup.name = offset;
+        inp->coda_lookup.VFid = *fid;
+	inp->coda_lookup.name = offset;
+	inp->coda_lookup.flags = CLU_CASE_SENSITIVE;
         /* send Venus a null terminated string */
         memcpy((char *)(inp) + offset, name, length);
         *((char *)inp + offset + length) = '\0';
@@ -159,8 +160,8 @@
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	if ( !error ) {
-	        *resfid = outp->cfs_lookup.VFid;
-		*type = outp->cfs_lookup.vtype;
+	        *resfid = outp->coda_lookup.VFid;
+		*type = outp->coda_lookup.vtype;
 	}
 	if (inp) CODA_FREE(inp, insize);
 		
@@ -168,17 +169,23 @@
 }
 
 
-int venus_release(struct super_block *sb, struct ViceFid *fid, int flags)
+int venus_release(struct super_block *sb, struct ViceFid *fid, int flags,
+		  struct coda_cred *cred)
 {
         union inputArgs *inp;
         union outputArgs *outp;
         int insize, outsize, error;
 	
 	insize = SIZE(close);
-	UPARG(CFS_CLOSE);
-
-        inp->cfs_close.VFid = *fid;
-        inp->cfs_close.flags = flags;
+	UPARG(CODA_CLOSE);
+	
+	if ( cred ) {
+		memcpy(&(inp->ih.cred), cred, sizeof(*cred));
+	} else 
+		printk("CODA: close without valid file creds.\n");
+	
+        inp->coda_close.VFid = *fid;
+        inp->coda_close.flags = flags;
 
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
@@ -195,16 +202,16 @@
         int insize, outsize, error;
        
 	insize = SIZE(open);
-	UPARG(CFS_OPEN);
+	UPARG(CODA_OPEN);
 
-        inp->cfs_open.VFid = *fid;
-        inp->cfs_open.flags = flags;
+        inp->coda_open.VFid = *fid;
+        inp->coda_open.flags = flags;
 
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	if ( !error ) {
-	        *ino = outp->cfs_open.inode;
-	        *dev = outp->cfs_open.dev;
+	        *ino = outp->coda_open.inode;
+	        *dev = outp->coda_open.dev;
 	} else {
 	        *ino = 0;
 		*dev = 0;
@@ -227,19 +234,19 @@
 
 	offset = INSIZE(mkdir);
 	insize = max(offset + length + 1, OUTSIZE(mkdir));
-	UPARG(CFS_MKDIR);
+	UPARG(CODA_MKDIR);
 
-        inp->cfs_mkdir.VFid = *dirfid;
-        inp->cfs_mkdir.attr = *attrs;
-	inp->cfs_mkdir.name = offset;
+        inp->coda_mkdir.VFid = *dirfid;
+        inp->coda_mkdir.attr = *attrs;
+	inp->coda_mkdir.name = offset;
         /* Venus must get null terminated string */
         memcpy((char *)(inp) + offset, name, length);
         *((char *)inp + offset + length) = '\0';
         
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-	*attrs = outp->cfs_mkdir.attr;
-	*newfid = outp->cfs_mkdir.VFid;
+	*attrs = outp->coda_mkdir.attr;
+	*newfid = outp->coda_mkdir.VFid;
 
 	if (inp) 
 	        CODA_FREE(inp, insize);
@@ -260,11 +267,11 @@
 	offset = INSIZE(rename);
 	insize = max(offset + new_length + old_length + 8,
 		     OUTSIZE(rename)); 
- 	UPARG(CFS_RENAME);
+ 	UPARG(CODA_RENAME);
 
-        inp->cfs_rename.sourceFid = *old_fid;
-        inp->cfs_rename.destFid =  *new_fid;
-        inp->cfs_rename.srcname = offset;
+        inp->coda_rename.sourceFid = *old_fid;
+        inp->coda_rename.destFid =  *new_fid;
+        inp->coda_rename.srcname = offset;
 
         /* Venus must receive an null terminated string */
         s = ( old_length & ~0x3) +4; /* round up to word boundary */
@@ -273,13 +280,13 @@
 
         /* another null terminated string for Venus */
         offset += s;
-        inp->cfs_rename.destname = offset;
+        inp->coda_rename.destname = offset;
         s = ( new_length & ~0x3) +4; /* round up to word boundary */
         memcpy((char *)(inp) + offset, new_name, new_length);
         *((char *)inp + offset + new_length) = '\0';
 
         CDEBUG(D_INODE, "destname in packet: %s\n", 
-              (char *)inp + (int) inp->cfs_rename.destname);
+              (char *)inp + (int) inp->coda_rename.destname);
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
 	if (inp) CODA_FREE(inp, insize);
@@ -297,14 +304,14 @@
 
         offset = INSIZE(create);
 	insize = max(offset + length + 1, OUTSIZE(create));
-	UPARG(CFS_CREATE);
+	UPARG(CODA_CREATE);
 
-        inp->cfs_create.VFid = *dirfid;
-        inp->cfs_create.attr.va_mode = mode;
-        inp->cfs_create.attr.va_rdev = rdev;
-	inp->cfs_create.excl = excl;
-        inp->cfs_create.mode = mode;
-        inp->cfs_create.name = offset;
+        inp->coda_create.VFid = *dirfid;
+        inp->coda_create.attr.va_mode = mode;
+        inp->coda_create.attr.va_rdev = rdev;
+	inp->coda_create.excl = excl;
+        inp->coda_create.mode = mode;
+        inp->coda_create.name = offset;
 
         /* Venus must get null terminated string */
         memcpy((char *)(inp) + offset, name, length);
@@ -312,8 +319,8 @@
                 
         error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
-	*attrs = outp->cfs_create.attr;
-	*newfid = outp->cfs_create.VFid;
+	*attrs = outp->coda_create.attr;
+	*newfid = outp->coda_create.VFid;
 
 	if (inp) 
 	        CODA_FREE(inp, insize);
@@ -330,10 +337,10 @@
 
         offset = INSIZE(rmdir);
 	insize = max(offset + length + 1, OUTSIZE(rmdir));
-	UPARG(CFS_RMDIR);
+	UPARG(CODA_RMDIR);
 
-        inp->cfs_rmdir.VFid = *dirfid;
-        inp->cfs_rmdir.name = offset;
+        inp->coda_rmdir.VFid = *dirfid;
+        inp->coda_rmdir.name = offset;
         memcpy((char *)(inp) + offset, name, length);
 	*((char *)inp + offset + length) = '\0';
         
@@ -352,10 +359,10 @@
 
         offset = INSIZE(remove);
 	insize = max(offset + length + 1, OUTSIZE(remove));
-	UPARG(CFS_REMOVE);
+	UPARG(CODA_REMOVE);
 
-        inp->cfs_remove.VFid = *dirfid;
-        inp->cfs_remove.name = offset;
+        inp->coda_remove.VFid = *dirfid;
+        inp->coda_remove.name = offset;
         memcpy((char *)(inp) + offset, name, length);
 	*((char *)inp + offset + length) = '\0';
         
@@ -375,18 +382,18 @@
         char *result;
         
 	insize = max(INSIZE(readlink), OUTSIZE(readlink)+ *length + 1);
-	UPARG(CFS_READLINK);
+	UPARG(CODA_READLINK);
 
-        inp->cfs_readlink.VFid = *fid;
+        inp->coda_readlink.VFid = *fid;
     
         error =  coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 	
 	if (! error) {
-                retlen = outp->cfs_readlink.count;
+                retlen = outp->coda_readlink.count;
 		if ( retlen > *length )
 		        retlen = *length;
 		*length = retlen;
-		result =  (char *)outp + (int)outp->cfs_readlink.data;
+		result =  (char *)outp + (int)outp->coda_readlink.data;
 		memcpy(buffer, result, retlen);
 		*(buffer + retlen) = '\0';
 	}
@@ -409,11 +416,11 @@
 
 	offset = INSIZE(link);
 	insize = max(offset  + len + 1, OUTSIZE(link));
-        UPARG(CFS_LINK);
+        UPARG(CODA_LINK);
 
-        inp->cfs_link.sourceFid = *fid;
-        inp->cfs_link.destFid = *dirfid;
-        inp->cfs_link.tname = offset;
+        inp->coda_link.sourceFid = *fid;
+        inp->coda_link.destFid = *dirfid;
+        inp->coda_link.tname = offset;
 
         /* make sure strings are null terminated */
         memcpy((char *)(inp) + offset, name, len);
@@ -439,20 +446,20 @@
 
         offset = INSIZE(symlink);
 	insize = max(offset + len + symlen + 8, OUTSIZE(symlink));
-	UPARG(CFS_SYMLINK);
+	UPARG(CODA_SYMLINK);
         
-        /*        inp->cfs_symlink.attr = *tva; XXXXXX */ 
-        inp->cfs_symlink.VFid = *fid;
+        /*        inp->coda_symlink.attr = *tva; XXXXXX */ 
+        inp->coda_symlink.VFid = *fid;
 
 	/* Round up to word boundary and null terminate */
-        inp->cfs_symlink.srcname = offset;
+        inp->coda_symlink.srcname = offset;
         s = ( symlen  & ~0x3 ) + 4; 
         memcpy((char *)(inp) + offset, symname, symlen);
         *((char *)inp + offset + symlen) = '\0';
         
 	/* Round up to word boundary and null terminate */
         offset += s;
-        inp->cfs_symlink.tname = offset;
+        inp->coda_symlink.tname = offset;
         s = (len & ~0x3) + 4;
         memcpy((char *)(inp) + offset, name, len);
         *((char *)inp + offset + len) = '\0';
@@ -473,9 +480,9 @@
 	int insize, outsize, error;
 	
 	insize=SIZE(fsync);
-	UPARG(CFS_FSYNC);
+	UPARG(CODA_FSYNC);
 
-        inp->cfs_fsync.VFid = *fid;
+        inp->coda_fsync.VFid = *fid;
         error = coda_upcall(coda_sbp(sb), sizeof(union inputArgs), 
                             &outsize, inp);
 
@@ -491,10 +498,10 @@
 	int insize, outsize, error;
 
 	insize = SIZE(access);
-	UPARG(CFS_ACCESS);
+	UPARG(CODA_ACCESS);
 
-        inp->cfs_access.VFid = *fid;
-        inp->cfs_access.flags = mask;
+        inp->coda_access.VFid = *fid;
+        inp->coda_access.flags = mask;
 
 	error = coda_upcall(coda_sbp(sb), insize, &outsize, inp);
 
@@ -513,7 +520,7 @@
 	int iocsize;
 
 	insize = VC_MAXMSGSIZE;
-	UPARG(CFS_IOCTL);
+	UPARG(CODA_IOCTL);
 
         /* build packet for Venus */
         if (data->vi.in_size > VC_MAXDATASIZE) {
@@ -521,21 +528,21 @@
 		goto exit;
         }
 
-        inp->cfs_ioctl.VFid = *fid;
+        inp->coda_ioctl.VFid = *fid;
     
         /* the cmd field was mutated by increasing its size field to
          * reflect the path and follow args. We need to subtract that
          * out before sending the command to Venus.  */
-        inp->cfs_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));	
+        inp->coda_ioctl.cmd = (cmd & ~(PIOCPARM_MASK << 16));	
         iocsize = ((cmd >> 16) & PIOCPARM_MASK) - sizeof(char *) - sizeof(int);
-        inp->cfs_ioctl.cmd |= (iocsize & PIOCPARM_MASK) <<	16;	
+        inp->coda_ioctl.cmd |= (iocsize & PIOCPARM_MASK) <<	16;	
     
-        /* in->cfs_ioctl.rwflag = flag; */
-        inp->cfs_ioctl.len = data->vi.in_size;
-        inp->cfs_ioctl.data = (char *)(INSIZE(ioctl));
+        /* in->coda_ioctl.rwflag = flag; */
+        inp->coda_ioctl.len = data->vi.in_size;
+        inp->coda_ioctl.data = (char *)(INSIZE(ioctl));
      
         /* get the data out of user space */
-        if ( copy_from_user((char*)inp + (int)inp->cfs_ioctl.data,
+        if ( copy_from_user((char*)inp + (int)inp->coda_ioctl.data,
 			    data->vi.in, data->vi.in_size) ) {
 	        error = EINVAL;
 	        goto exit;
@@ -550,9 +557,9 @@
 	}
         
 	/* Copy out the OUT buffer. */
-        if (outp->cfs_ioctl.len > data->vi.out_size) {
+        if (outp->coda_ioctl.len > data->vi.out_size) {
                 CDEBUG(D_FILE, "return len %d <= request len %d\n",
-                      outp->cfs_ioctl.len, 
+                      outp->coda_ioctl.len, 
                       data->vi.out_size);
                 error = EINVAL;
         } else {
@@ -561,7 +568,7 @@
 		if ( error ) goto exit;
 
 		if (copy_to_user(data->vi.out, 
-				 (char *)outp + (int)outp->cfs_ioctl.data, 
+				 (char *)outp + (int)outp->coda_ioctl.data, 
 				 data->vi.out_size)) {
 		        error = EINVAL;
 			goto exit;
@@ -579,15 +586,15 @@
  * 
  */
 
-static inline unsigned long coda_waitfor_upcall(struct vmsg *vmp)
+static inline unsigned long coda_waitfor_upcall(struct upc_req *vmp)
 {
 	struct wait_queue	wait = { current, NULL };
 	unsigned long posttime;
 
-	vmp->vm_posttime = jiffies;
+	vmp->uc_posttime = jiffies;
 	posttime = jiffies;
 
-	add_wait_queue(&vmp->vm_sleep, &wait);
+	add_wait_queue(&vmp->uc_sleep, &wait);
 	for (;;) {
 		if ( coda_hard == 0 ) 
 			current->state = TASK_INTERRUPTIBLE;
@@ -595,7 +602,7 @@
 			current->state = TASK_UNINTERRUPTIBLE;
 
 		/* got a reply */
-		if ( vmp->vm_flags & VM_WRITE )
+		if ( vmp->uc_flags & REQ_WRITE )
 			break;
 
 		if ( !coda_hard && signal_pending(current) ) {
@@ -605,13 +612,13 @@
 				break;
 			/* signal is present: after timeout always return 
 			   really smart idea, probably useless ... */
-			if ( jiffies > vmp->vm_posttime + coda_timeout * HZ )
+			if ( jiffies - vmp->uc_posttime > coda_timeout * HZ )
 				break; 
 		}
 		schedule();
 
 	}
-	remove_wait_queue(&vmp->vm_sleep, &wait);
+	remove_wait_queue(&vmp->uc_sleep, &wait);
 	current->state = TASK_RUNNING;
 
 	CDEBUG(D_SPECIAL, "posttime: %ld, returned: %ld\n", posttime, jiffies-posttime);
@@ -635,40 +642,37 @@
 		union inputArgs *buffer) 
 {
 	unsigned long runtime; 
-	struct vcomm *vcommp;
+	struct venus_comm *vcommp;
 	union outputArgs *out;
-	struct vmsg *vmp;
+	struct upc_req *req;
 	int error = 0;
 
 ENTRY;
 
-	if (sbi->sbi_vcomm == NULL) {
-                return -ENODEV;
-	}
-	vcommp = sbi->sbi_vcomm;
-
-
-	if (!vcomm_open(vcommp))
+	vcommp = &coda_upc_comm;
+	if ( !vcommp->vc_pid ) {
+		printk("No pseudo device in upcall comms at %p\n", vcommp);
                 return -ENXIO;
+	}
 
 	/* Format the request message. */
-	CODA_ALLOC(vmp,struct vmsg *,sizeof(struct vmsg));
-	vmp->vm_data = (void *)buffer;
-	vmp->vm_flags = 0;
-	vmp->vm_inSize = inSize;
-	vmp->vm_outSize = *outSize ? *outSize : inSize;
-	vmp->vm_opcode = ((union inputArgs *)buffer)->ih.opcode;
-	vmp->vm_unique = ++vcommp->vc_seq;
-        vmp->vm_sleep = NULL;
+	CODA_ALLOC(req,struct upc_req *,sizeof(struct upc_req));
+	req->uc_data = (void *)buffer;
+	req->uc_flags = 0;
+	req->uc_inSize = inSize;
+	req->uc_outSize = *outSize ? *outSize : inSize;
+	req->uc_opcode = ((union inputArgs *)buffer)->ih.opcode;
+	req->uc_unique = ++vcommp->vc_seq;
+        req->uc_sleep = NULL;
 	
 	/* Fill in the common input args. */
-	((union inputArgs *)buffer)->ih.unique = vmp->vm_unique;
+	((union inputArgs *)buffer)->ih.unique = req->uc_unique;
 
 	/* Append msg to pending queue and poke Venus. */
-	coda_q_insert(&(vmp->vm_chain), &(vcommp->vc_pending));
+	list_add(&(req->uc_chain), vcommp->vc_pending.prev);
 	CDEBUG(D_UPCALL, 
 	       "Proc %d wake Venus for(opc,uniq) =(%d,%d) msg at %x.zzz.\n",
-	       current->pid, vmp->vm_opcode, vmp->vm_unique, (int)vmp);
+	       current->pid, req->uc_opcode, req->uc_unique, (int)req);
 
 	wake_up_interruptible(&vcommp->vc_waitq);
 	/* We can be interrupted while we wait for Venus to process
@@ -681,19 +685,19 @@
 	 * ENODEV.  */
 
 	/* Go to sleep.  Wake up on signals only after the timeout. */
-	runtime = coda_waitfor_upcall(vmp);
+	runtime = coda_waitfor_upcall(req);
 	coda_upcall_stats(((union inputArgs *)buffer)->ih.opcode, runtime);
 
 	CDEBUG(D_TIMING, "opc: %d time: %ld uniq: %d size: %d\n",
-	       vmp->vm_opcode, jiffies - vmp->vm_posttime, 
-	       vmp->vm_unique, vmp->vm_outSize);
+	       req->uc_opcode, jiffies - req->uc_posttime, 
+	       req->uc_unique, req->uc_outSize);
 	CDEBUG(D_UPCALL, 
-	       "..process %d woken up by Venus for vmp at 0x%x, data at %x\n", 
-	       current->pid, (int)vmp, (int)vmp->vm_data);
-	if (vcomm_open(vcommp)) {      /* i.e. Venus is still alive */
+	       "..process %d woken up by Venus for req at 0x%x, data at %x\n", 
+	       current->pid, (int)req, (int)req->uc_data);
+	if (vcommp->vc_pid) {      /* i.e. Venus is still alive */
 	    /* Op went through, interrupt or not... */
-	    if (vmp->vm_flags & VM_WRITE) {
-		out = (union outputArgs *)vmp->vm_data;
+	    if (req->uc_flags & REQ_WRITE) {
+		out = (union outputArgs *)req->uc_data;
 		/* here we map positive Venus errors to kernel errors */
 		if ( out->oh.result < 0 ) {
 			printk("Tell Peter: Venus returns negative error %ld, for oc %ld!\n",
@@ -704,49 +708,49 @@
 		CDEBUG(D_UPCALL, 
 		       "upcall: (u,o,r) (%ld, %ld, %ld) out at %p\n", 
 		       out->oh.unique, out->oh.opcode, out->oh.result, out);
-		*outSize = vmp->vm_outSize;
+		*outSize = req->uc_outSize;
 		goto exit;
 	    }
-	    if ( !(vmp->vm_flags & VM_READ) && signal_pending(current)) { 
+	    if ( !(req->uc_flags & REQ_READ) && signal_pending(current)) { 
 		/* Interrupted before venus read it. */
 		CDEBUG(D_UPCALL, 
 		       "Interrupted before read:(op,un) (%d.%d), flags = %x\n",
-		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
-		coda_q_remove(&(vmp->vm_chain));
+		       req->uc_opcode, req->uc_unique, req->uc_flags);
+		list_del(&(req->uc_chain));
 		/* perhaps the best way to convince the app to
 		   give up? */
 		error = -EINTR;
 		goto exit;
 	    } 
-	    if ( (vmp->vm_flags & VM_READ) && signal_pending(current) ) {
+	    if ( (req->uc_flags & REQ_READ) && signal_pending(current) ) {
 		    /* interrupted after Venus did its read, send signal */
-		    union inputArgs *dog;
-		    struct vmsg *svmp;
+		    union inputArgs *sig_inputArgs;
+		    struct upc_req *sig_req;
 		    
 		    CDEBUG(D_UPCALL, 
 			   "Sending Venus a signal: op = %d.%d, flags = %x\n",
-			   vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
+			   req->uc_opcode, req->uc_unique, req->uc_flags);
 		    
-		    coda_q_remove(&(vmp->vm_chain));
+		    list_del(&(req->uc_chain));
 		    error = -EINTR;
-		    CODA_ALLOC(svmp, struct vmsg *, sizeof (struct vmsg));
-		    CODA_ALLOC((svmp->vm_data), char *, sizeof(struct cfs_in_hdr));
+		    CODA_ALLOC(sig_req, struct upc_req *, sizeof (struct upc_req));
+		    CODA_ALLOC((sig_req->uc_data), char *, sizeof(struct coda_in_hdr));
 		    
-		    dog = (union inputArgs *)svmp->vm_data;
-		    dog->ih.opcode = CFS_SIGNAL;
-		    dog->ih.unique = vmp->vm_unique;
+		    sig_inputArgs = (union inputArgs *)sig_req->uc_data;
+		    sig_inputArgs->ih.opcode = CODA_SIGNAL;
+		    sig_inputArgs->ih.unique = req->uc_unique;
 		    
-		    svmp->vm_flags = 0;
-		    svmp->vm_opcode = dog->ih.opcode;
-		    svmp->vm_unique = dog->ih.unique;
-		    svmp->vm_inSize = sizeof(struct cfs_in_hdr);
-		    svmp->vm_outSize = sizeof(struct cfs_in_hdr);
+		    sig_req->uc_flags = REQ_ASYNC;
+		    sig_req->uc_opcode = sig_inputArgs->ih.opcode;
+		    sig_req->uc_unique = sig_inputArgs->ih.unique;
+		    sig_req->uc_inSize = sizeof(struct coda_in_hdr);
+		    sig_req->uc_outSize = sizeof(struct coda_in_hdr);
 		    CDEBUG(D_UPCALL, 
 			   "coda_upcall: enqueing signal msg (%d, %d)\n",
-			   svmp->vm_opcode, svmp->vm_unique);
+			   sig_req->uc_opcode, sig_req->uc_unique);
 		    
 		    /* insert at head of queue! */
-		    coda_q_insert(&(svmp->vm_chain), vcommp->vc_pending.forw);
+		    list_add(&(sig_req->uc_chain), &vcommp->vc_pending);
 		    wake_up_interruptible(&vcommp->vc_waitq);
 	    } else {
 		    printk("Coda: Strange interruption..\n");
@@ -754,12 +758,12 @@
 	    }
 	} else {	/* If venus died i.e. !VC_OPEN(vcommp) */
 	        printk("coda_upcall: Venus dead on (op,un) (%d.%d) flags %d\n",
-		       vmp->vm_opcode, vmp->vm_unique, vmp->vm_flags);
+		       req->uc_opcode, req->uc_unique, req->uc_flags);
 		error = -ENODEV;
 	}
 
  exit:
-	CODA_FREE(vmp, sizeof(struct vmsg));
+	CODA_FREE(req, sizeof(struct upc_req));
 	if (error) 
 	        badclstats();
 	return error;
@@ -778,26 +782,26 @@
  * There are 7 cases where cache invalidations occur.  The semantics
  *  of each is listed here:
  *
- * CFS_FLUSH     -- flush all entries from the name cache and the cnode cache.
- * CFS_PURGEUSER -- flush all entries from the name cache for a specific user
+ * CODA_FLUSH     -- flush all entries from the name cache and the cnode cache.
+ * CODA_PURGEUSER -- flush all entries from the name cache for a specific user
  *                  This call is a result of token expiration.
  *
  * The next arise as the result of callbacks on a file or directory.
- * CFS_ZAPFILE   -- flush the cached attributes for a file.
+ * CODA_ZAPFILE   -- flush the cached attributes for a file.
 
- * CFS_ZAPDIR    -- flush the attributes for the dir and
+ * CODA_ZAPDIR    -- flush the attributes for the dir and
  *                  force a new lookup for all the children
                     of this dir.
 
  *
  * The next is a result of Venus detecting an inconsistent file.
- * CFS_PURGEFID  -- flush the attribute for the file
+ * CODA_PURGEFID  -- flush the attribute for the file
  *                  purge it and its children from the dcache
  *
  * The last  allows Venus to replace local fids with global ones
  * during reintegration.
  *
- * CFS_REPLACE -- replace one ViceFid with another throughout the name cache */
+ * CODA_REPLACE -- replace one ViceFid with another throughout the name cache */
 
 int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
 {
@@ -810,37 +814,38 @@
 
 	  switch (opcode) {
 
-	  case CFS_FLUSH : {
-	           clstats(CFS_FLUSH);
-		   CDEBUG(D_DOWNCALL, "CFS_FLUSH\n");
+	  case CODA_FLUSH : {
+	           clstats(CODA_FLUSH);
+		   CDEBUG(D_DOWNCALL, "CODA_FLUSH\n");
 		   coda_cache_clear_all(sb);
 		   shrink_dcache_sb(sb);
+		   coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
 		   return(0);
 	  }
 
-	  case CFS_PURGEUSER : {
-	           struct coda_cred *cred = &out->cfs_purgeuser.cred;
-		   CDEBUG(D_DOWNCALL, "CFS_PURGEUSER\n");
+	  case CODA_PURGEUSER : {
+	           struct coda_cred *cred = &out->coda_purgeuser.cred;
+		   CDEBUG(D_DOWNCALL, "CODA_PURGEUSER\n");
 		   if ( !cred ) {
 		           printk("PURGEUSER: null cred!\n");
 			   return 0;
 		   }
-		   clstats(CFS_PURGEUSER);
+		   clstats(CODA_PURGEUSER);
 		   coda_cache_clear_cred(sb, cred);
 		   return(0);
 	  }
 
-	  case CFS_ZAPDIR : {
+	  case CODA_ZAPDIR : {
 	          struct inode *inode;
-		  ViceFid *fid = &out->cfs_zapdir.CodaFid;
+		  ViceFid *fid = &out->coda_zapdir.CodaFid;
 		  CDEBUG(D_DOWNCALL, "zapdir: fid = %s...\n", coda_f2s(fid));
-		  clstats(CFS_ZAPDIR);
+		  clstats(CODA_ZAPDIR);
 
 		  inode = coda_fid_to_inode(fid, sb);
 		  if (inode) {
 			  CDEBUG(D_DOWNCALL, "zapdir: inode = %ld children flagged\n", 
 				 inode->i_ino);
-			  coda_purge_children(inode);
+			  coda_flag_inode_children(inode, C_PURGE);
 			  CDEBUG(D_DOWNCALL, "zapdir: inode = %ld cache cleared\n", inode->i_ino);
 	                  coda_flag_inode(inode, C_VATTR);
 		  } else 
@@ -849,10 +854,10 @@
 		  return(0);
 	  }
 
-	  case CFS_ZAPFILE : {
+	  case CODA_ZAPFILE : {
 	          struct inode *inode;
-		  struct ViceFid *fid = &out->cfs_zapfile.CodaFid;
-		  clstats(CFS_ZAPFILE);
+		  struct ViceFid *fid = &out->coda_zapfile.CodaFid;
+		  clstats(CODA_ZAPFILE);
 		  CDEBUG(D_DOWNCALL, "zapfile: fid = %s\n", coda_f2s(fid));
 		  inode = coda_fid_to_inode(fid, sb);
 		  if ( inode ) {
@@ -863,27 +868,27 @@
 		  return 0;
 	  }
 
-	  case CFS_PURGEFID : {
+	  case CODA_PURGEFID : {
 	          struct inode *inode;
-		  ViceFid *fid = &out->cfs_purgefid.CodaFid;
+		  ViceFid *fid = &out->coda_purgefid.CodaFid;
 		  CDEBUG(D_DOWNCALL, "purgefid: fid = %s\n", coda_f2s(fid));
-		  clstats(CFS_PURGEFID);
+		  clstats(CODA_PURGEFID);
 		  inode = coda_fid_to_inode(fid, sb);
 		  if ( inode ) { 
 			  CDEBUG(D_DOWNCALL, "purgefid: inode = %ld\n", inode->i_ino);
-			  coda_purge_children(inode);
+			  coda_flag_inode_children(inode, C_PURGE);
 			  coda_purge_dentries(inode);
 		  }else 
 			  CDEBUG(D_DOWNCALL, "purgefid: no inode\n");
 		  return 0;
 	  }
 
-	  case CFS_REPLACE : {
+	  case CODA_REPLACE : {
 	          struct inode *inode;
-		  ViceFid *oldfid = &out->cfs_replace.OldFid;
-		  ViceFid *newfid = &out->cfs_replace.NewFid;
-		  clstats(CFS_REPLACE);
-		  CDEBUG(D_DOWNCALL, "CFS_REPLACE\n");
+		  ViceFid *oldfid = &out->coda_replace.OldFid;
+		  ViceFid *newfid = &out->coda_replace.NewFid;
+		  clstats(CODA_REPLACE);
+		  CDEBUG(D_DOWNCALL, "CODA_REPLACE\n");
 		  inode = coda_fid_to_inode(oldfid, sb);
 		  if ( inode ) { 
 			  CDEBUG(D_DOWNCALL, "replacefid: inode = %ld\n", inode->i_ino);
diff -u --recursive --new-file v2.1.131/linux/fs/dcache.c linux/fs/dcache.c
--- v2.1.131/linux/fs/dcache.c	Wed Aug 26 11:37:40 1998
+++ linux/fs/dcache.c	Mon Dec 21 14:11:24 1998
@@ -161,17 +161,17 @@
 
 /*
  * Try to invalidate the dentry if it turns out to be
- * possible. If there are other users of the dentry we
- * can't invalidate it.
+ * possible. If there are other dentries that can be
+ * reached through this one we can't delete it.
  */
 int d_invalidate(struct dentry * dentry)
 {
 	/* Check whether to do a partial shrink_dcache */
-	if (!list_empty(&dentry->d_subdirs))
+	if (!list_empty(&dentry->d_subdirs)) {
 		shrink_dcache_parent(dentry);
-
-	if (dentry->d_count != 1)
-		return -EBUSY;
+		if (!list_empty(&dentry->d_subdirs))
+			return -EBUSY;
+	}
 
 	d_drop(dentry);
 	return 0;
diff -u --recursive --new-file v2.1.131/linux/fs/ext2/file.c linux/fs/ext2/file.c
--- v2.1.131/linux/fs/ext2/file.c	Wed Aug 26 11:37:40 1998
+++ linux/fs/ext2/file.c	Mon Dec 21 15:22:54 1998
@@ -272,10 +272,6 @@
 		mark_buffer_uptodate(bh, 1);
 		mark_buffer_dirty(bh, 0);
 
-		/* Mark the buffer untouched if we'll move on to the next one.. */
-		if (!(pos & (sb->s_blocksize-1)))
-			clear_bit(BH_Touched, &bh->b_state);
-
 		if (filp->f_flags & O_SYNC)
 			bufferlist[buffercount++] = bh;
 		else
diff -u --recursive --new-file v2.1.131/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.1.131/linux/fs/ext2/namei.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/ext2/namei.c	Fri Dec 18 07:09:35 1998
@@ -430,19 +430,6 @@
 		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
 					      EXT2_FEATURE_INCOMPAT_FILETYPE))
 			de->file_type = EXT2_FT_REG_FILE;
-	} else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &ext2_dir_inode_operations;
-		if (dir->i_mode & S_ISGID)
-			inode->i_mode |= S_ISGID;
-		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-					      EXT2_FEATURE_INCOMPAT_FILETYPE))
-			de->file_type = EXT2_FT_DIR;
-	}
-	else if (S_ISLNK(inode->i_mode)) {
-		inode->i_op = &ext2_symlink_inode_operations;
-		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
-					      EXT2_FEATURE_INCOMPAT_FILETYPE))
-			de->file_type = EXT2_FT_SYMLINK;
 	} else if (S_ISCHR(inode->i_mode)) {
 		inode->i_op = &chrdev_inode_operations;
 		if (EXT2_HAS_INCOMPAT_FEATURE(dir->i_sb,
@@ -643,21 +630,7 @@
 	inode = dentry->d_inode;
 	DQUOT_INIT(inode);
 
-	retval = -EPERM;
-	if ((dir->i_mode & S_ISVTX) && 
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rmdir;
-	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-		goto end_rmdir;
-
-	retval = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto end_rmdir;
-
 	retval = -EIO;
-	if (inode->i_dev != dir->i_dev)
-		goto end_rmdir;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
 		goto end_rmdir;
 
@@ -715,14 +688,6 @@
 	inode = dentry->d_inode;
 	DQUOT_INIT(inode);
 
-	retval = -EPERM;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		goto end_unlink;
-	if ((dir->i_mode & S_ISVTX) &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto end_unlink;
-
 	retval = -EIO;
 	if (le32_to_cpu(de->inode) != inode->i_ino)
 		goto end_unlink;
@@ -910,17 +875,15 @@
 		goto end_rename;
 
 	old_bh = ext2_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
-	retval = -ENOENT;
-	if (!old_bh)
-		goto end_rename;
+	/*
+	 *  Check for inode number is _not_ due to possible IO errors.
+	 *  We might rmdir the source, keep it as pwd of some process
+	 *  and merrily kill the link to whatever was created under the
+	 *  same name. Goodbye sticky bit ;-<
+	 */
 	old_inode = old_dentry->d_inode;
-
-	retval = -EPERM;
-	if ((old_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != old_inode->i_uid &&
-	    current->fsuid != old_dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rename;
-	if (IS_APPEND(old_inode) || IS_IMMUTABLE(old_inode))
+	retval = -ENOENT;
+	if (!old_bh || le32_to_cpu(old_de->inode) != old_inode->i_ino)
 		goto end_rename;
 
 	new_inode = new_dentry->d_inode;
@@ -937,39 +900,21 @@
 	retval = 0;
 	if (new_inode == old_inode)
 		goto end_rename;
-	if (new_inode && S_ISDIR(new_inode->i_mode)) {
-		retval = -EISDIR;
-		if (!S_ISDIR(old_inode->i_mode))
-			goto end_rename;
-		retval = -EINVAL;
-		if (is_subdir(new_dentry, old_dentry))
-			goto end_rename;
-		/* Prune any children before testing for busy */
-		if (new_dentry->d_count > 1)
-			shrink_dcache_parent(new_dentry);
-		retval = -ENOTEMPTY;
-		if (!empty_dir (new_inode))
-			goto end_rename;
-		retval = -EBUSY;
-		if (new_dentry->d_count > 1)
-			goto end_rename;
-	}
-	retval = -EPERM;
-	if (new_inode) {
-		if ((new_dir->i_mode & S_ISVTX) &&
-		    current->fsuid != new_inode->i_uid &&
-		    current->fsuid != new_dir->i_uid && !capable(CAP_FOWNER))
-			goto end_rename;
-		if (IS_APPEND(new_inode) || IS_IMMUTABLE(new_inode))
-			goto end_rename;
-	}
 	if (S_ISDIR(old_inode->i_mode)) {
-		retval = -ENOTDIR;
-		if (new_inode && !S_ISDIR(new_inode->i_mode))
-			goto end_rename;
 		retval = -EINVAL;
 		if (is_subdir(new_dentry, old_dentry))
 			goto end_rename;
+		if (new_inode) {
+			/* Prune any children before testing for busy */
+			if (new_dentry->d_count > 1)
+				shrink_dcache_parent(new_dentry);
+			retval = -EBUSY;
+			if (new_dentry->d_count > 1)
+				goto end_rename;
+			retval = -ENOTEMPTY;
+			if (!empty_dir (new_inode))
+				goto end_rename;
+		}
 		dir_bh = ext2_bread (old_inode, 0, 0, &retval);
 		if (!dir_bh)
 			goto end_rename;
diff -u --recursive --new-file v2.1.131/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.1.131/linux/fs/hfs/dir.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/hfs/dir.c	Wed Dec 16 12:17:21 1998
@@ -337,9 +337,6 @@
 	struct hfs_cat_key key;
 	int error;
 
-	if (parent == inode) /* can't delete . */
-		return -EPERM;
-
 	if (build_key(&key, parent, dentry->d_name.name,
 		      dentry->d_name.len))
 		return -EPERM;
diff -u --recursive --new-file v2.1.131/linux/fs/minix/namei.c linux/fs/minix/namei.c
--- v2.1.131/linux/fs/minix/namei.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/minix/namei.c	Fri Dec 18 07:09:35 1998
@@ -267,13 +267,6 @@
 	inode->i_op = NULL;
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &minix_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &minix_dir_inode_operations;
-		if (dir->i_mode & S_ISGID)
-			inode->i_mode |= S_ISGID;
-	}
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &minix_symlink_inode_operations;
 	else if (S_ISCHR(inode->i_mode))
 		inode->i_op = &chrdev_inode_operations;
 	else if (S_ISBLK(inode->i_mode))
@@ -429,21 +422,8 @@
 	retval = -ENOENT;
 	if (!bh)
 		goto end_rmdir;
-	retval = -EPERM;
 	inode = dentry->d_inode;
 
-        if ((dir->i_mode & S_ISVTX) &&
-            current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rmdir;
-	if (inode->i_dev != dir->i_dev)
-		goto end_rmdir;
-	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-		goto end_rmdir;
-	if (!S_ISDIR(inode->i_mode)) {
-		retval = -ENOTDIR;
-		goto end_rmdir;
-	}
 	if (!empty_dir(inode)) {
 		retval = -ENOTEMPTY;
 		goto end_rmdir;
@@ -496,10 +476,6 @@
 		schedule();
 		goto repeat;
 	}
-	if ((dir->i_mode & S_ISVTX) &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto end_unlink;
 	if (de->inode != inode->i_ino) {
 		retval = -ENOENT;
 		goto end_unlink;
@@ -655,10 +631,6 @@
 		goto end_rename;
 	old_inode = old_dentry->d_inode;
 	retval = -EPERM;
-	if ((old_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != old_inode->i_uid &&
-	    current->fsuid != old_dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rename;
 	new_inode = new_dentry->d_inode;
 	new_bh = minix_find_entry(new_dir, new_dentry->d_name.name,
 				  new_dentry->d_name.len, &new_de);
@@ -672,32 +644,21 @@
 		retval = 0;
 		goto end_rename;
 	}
-	if (new_inode && S_ISDIR(new_inode->i_mode)) {
-		retval = -EISDIR;
-		if (!S_ISDIR(old_inode->i_mode))
-			goto end_rename;
-		retval = -EINVAL;
-		if (is_subdir(new_dentry, old_dentry))
-			goto end_rename;
-		retval = -ENOTEMPTY;
-		if (!empty_dir(new_inode))
-			goto end_rename;
-		retval = -EBUSY;
-		if (new_inode->i_count > 1)
-			goto end_rename;
-	}
-	retval = -EPERM;
-	if (new_inode && (new_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != new_inode->i_uid &&
-	    current->fsuid != new_dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rename;
 	if (S_ISDIR(old_inode->i_mode)) {
-		retval = -ENOTDIR;
-		if (new_inode && !S_ISDIR(new_inode->i_mode))
-			goto end_rename;
 		retval = -EINVAL;
 		if (is_subdir(new_dentry, old_dentry))
 			goto end_rename;
+		if (new_inode) {
+			/* Prune any children before testing for busy */
+			if (new_dentry->d_count > 1)
+				shrink_dcache_parent(new_dentry);
+			retval = -EBUSY;
+			if (new_dentry->d_count > 1)
+			retval = -ENOTEMPTY;
+			if (!empty_dir(new_inode))
+				goto end_rename;
+			retval = -EBUSY;
+		}
 		retval = -EIO;
 		dir_bh = minix_bread(old_inode,0,0);
 		if (!dir_bh)
diff -u --recursive --new-file v2.1.131/linux/fs/msdos/namei.c linux/fs/msdos/namei.c
--- v2.1.131/linux/fs/msdos/namei.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/msdos/namei.c	Fri Dec 18 07:09:35 1998
@@ -439,18 +439,10 @@
 				&bh, &de, &ino);
 	if (res < 0)
 		goto rmdir_done;
-	res = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto rmdir_done;
-	if (dir->i_dev != inode->i_dev || dir == inode)
-		printk("msdos_rmdir: impossible condition\n");
 	/*
-	 * Check whether the directory is empty, then prune
-	 * any child dentries and make sure it's not in use.
+	 * Check whether the directory is not in use, then check
+	 * whether it is empty.
 	 */
-	res = msdos_empty(inode);
-	if (res)
-		goto rmdir_done;
 	res = -EBUSY;
 	if (!list_empty(&dentry->d_hash)) {
 #ifdef MSDOS_DEBUG
@@ -459,6 +451,9 @@
 #endif
 		goto rmdir_done;
 	}
+	res = msdos_empty(inode);
+	if (res)
+		goto rmdir_done;
 
 	inode->i_nlink = 0;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
@@ -507,11 +502,14 @@
 
 	dir->i_nlink++;
 	inode->i_nlink = 2; /* no need to mark them dirty */
-	MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
+
+#ifdef whatfor
 	/*
-	 * Instantiate the dentry now, in case we need to cleanup.
+	 * He's dead, Jim. We don't d_instantiate anymore. Should do it
+	 * from the very beginning, actually.
 	 */
-	d_instantiate(dentry, inode);
+	MSDOS_I(inode)->i_busy = 1; /* prevent lookups */
+#endif
 
 	if ((res = fat_add_cluster(inode)) < 0)
 		goto mkdir_error;
@@ -531,8 +529,11 @@
 	MSDOS_I(dot)->i_logstart = MSDOS_I(dir)->i_logstart;
 	dot->i_nlink = dir->i_nlink;
 	mark_inode_dirty(dot);
+#ifdef whatfor
 	MSDOS_I(inode)->i_busy = 0;
+#endif
 	iput(dot);
+	d_instantiate(dentry, inode);
 	res = 0;
 
 out_unlock:
@@ -541,8 +542,17 @@
 
 mkdir_error:
 	printk("msdos_mkdir: error=%d, attempting cleanup\n", res);
-	if (msdos_rmdir(dir,dentry) < 0)
-		fat_fs_panic(dir->i_sb,"rmdir in mkdir failed");
+	bh = NULL;
+	fat_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY);
+	inode->i_nlink = 0;
+	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+	dir->i_nlink--;
+	mark_inode_dirty(inode);
+	mark_inode_dirty(dir);
+	iput(inode);
+	de->name[0] = DELETED_FLAG;
+	fat_mark_buffer_dirty(sb, bh, 1);
+	fat_brelse(sb, bh);
 	goto out_unlock;
 
 out_exist:
@@ -567,8 +577,6 @@
 		goto unlink_done;
 	res = -EPERM;
 	if (!S_ISREG(inode->i_mode) && nospc)
-		goto unlink_done;
-	if (IS_IMMUTABLE(inode))
 		goto unlink_done;
 	/* N.B. check for busy files? */
 
diff -u --recursive --new-file v2.1.131/linux/fs/namei.c linux/fs/namei.c
--- v2.1.131/linux/fs/namei.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/namei.c	Fri Dec 18 07:09:35 1998
@@ -490,6 +490,77 @@
 	return dentry;
 }
 
+/*
+ * It's inline, so penalty for filesystems that don't use sticky bit is
+ * minimal.
+ */
+static inline int check_sticky(struct inode *dir, struct inode *inode)
+{
+	if (!(dir->i_mode & S_ISVTX))
+		return 0;
+	if (inode->i_uid == current->fsuid)
+		return 0;
+	if (dir->i_uid == current->fsuid)
+		return 0;
+	return !capable(CAP_FOWNER);
+}
+
+/*
+ *	Check whether we can remove a link victim from directory dir, check
+ *  whether the type of victim is right.
+ *  1. We can't do it if dir is read-only (done in permission())
+ *  2. We should have write and exec permissions on dir
+ *  3. We can't remove anything from append-only dir
+ *  4. We can't do anything with immutable dir (done in permission())
+ *  5. If the sticky bit on dir is set we should either
+ *	a. be owner of dir, or
+ *	b. be owner of victim, or
+ *	c. have CAP_FOWNER capability
+ *  6. If the victim is append-only or immutable we can't do antyhing with
+ *     links pointing to it.
+ *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
+ *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
+ *  9. We can't remove a root or mountpoint.
+ */
+static inline int may_delete(struct inode *dir,struct dentry *victim, int isdir)
+{
+	int error;
+	if (!victim->d_inode || victim->d_parent->d_inode != dir)
+		return -ENOENT;
+	error = permission(dir,MAY_WRITE | MAY_EXEC);
+	if (error)
+		return error;
+	if (IS_APPEND(dir))
+		return -EPERM;
+	if (check_sticky(dir, victim->d_inode)||IS_APPEND(victim->d_inode)||
+	    IS_IMMUTABLE(victim->d_inode))
+		return -EPERM;
+	if (isdir) {
+		if (!S_ISDIR(victim->d_inode->i_mode))
+			return -ENOTDIR;
+		if (IS_ROOT(victim))
+			return -EBUSY;
+		if (victim->d_mounts != victim->d_covers)
+			return -EBUSY;
+	} else if (S_ISDIR(victim->d_inode->i_mode))
+		return -EISDIR;
+	return 0;
+}
+
+/*	Check whether we can create an object with dentry child in directory
+ *  dir.
+ *  1. We can't do it if child already exists (open has special treatment for
+ *     this case, but since we are inlined it's OK)
+ *  2. We can't do it if dir is read-only (done in permission())
+ *  3. We should have write and exec permissions on dir
+ *  4. We can't do it if dir is immutable (done in permission())
+ */
+static inline int may_create(struct inode *dir, struct dentry *child) {
+	if (child->d_inode)
+		return -EEXIST;
+	return permission(dir,MAY_WRITE | MAY_EXEC);
+}
+
 static inline struct dentry *get_parent(struct dentry *dentry)
 {
 	return dget(dentry->d_parent);
@@ -599,16 +670,16 @@
 			error = 0;
 			if (flag & O_EXCL)
 				error = -EEXIST;
-		} else if (IS_RDONLY(dir->d_inode))
-			error = -EROFS;
-		else if (!dir->d_inode->i_op || !dir->d_inode->i_op->create)
-			error = -EACCES;
-		else if ((error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC)) == 0) {
-			DQUOT_INIT(dir->d_inode);
-			error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode);
-			/* Don't check for write permission, don't truncate */
-			acc_mode = 0;
-			flag &= ~O_TRUNC;
+		} else if ((error = may_create(dir->d_inode, dentry)) == 0) {
+			if (!dir->d_inode->i_op || !dir->d_inode->i_op->create)
+				error = -EACCES;
+			else {
+				DQUOT_INIT(dir->d_inode);
+				error = dir->d_inode->i_op->create(dir->d_inode, dentry, mode);
+				/* Don't check for write permission, don't truncate */
+				acc_mode = 0;
+				flag &= ~O_TRUNC;
+			}
 		}
 		unlock_dir(dir);
 		if (error)
@@ -705,30 +776,20 @@
 	if (IS_ERR(dir))
 		goto exit;
 
-	retval = ERR_PTR(-EEXIST);
-	if (dentry->d_inode)
-		goto exit_lock;
-
-	retval = ERR_PTR(-EROFS);
-	if (IS_RDONLY(dir->d_inode))
-		goto exit_lock;
-
-	error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC);
-	retval = ERR_PTR(error);
+	error = may_create(dir->d_inode, dentry);
 	if (error)
 		goto exit_lock;
 
-	retval = ERR_PTR(-EPERM);
+	error = -EPERM;
 	if (!dir->d_inode->i_op || !dir->d_inode->i_op->mknod)
 		goto exit_lock;
 
 	DQUOT_INIT(dir->d_inode);
 	error = dir->d_inode->i_op->mknod(dir->d_inode, dentry, mode, dev);
+exit_lock:
 	retval = ERR_PTR(error);
 	if (!error)
 		retval = dget(dentry);
-
-exit_lock:
 	unlock_dir(dir);
 exit:
 	dput(dentry);
@@ -790,15 +851,7 @@
 	if (IS_ERR(dir))
 		goto exit_dput;
 
-	error = -EEXIST;
-	if (dentry->d_inode)
-		goto exit_lock;
-
-	error = -EROFS;
-	if (IS_RDONLY(dir->d_inode))
-		goto exit_lock;
-
-	error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC);
+	error = may_create(dir->d_inode, dentry);
 	if (error)
 		goto exit_lock;
 
@@ -865,58 +918,20 @@
 	dput(d2);
 }
 
-static inline int do_rmdir(const char * name)
-{
-	int error;
-	struct dentry *dir;
-	struct dentry *dentry;
-
-	dentry = lookup_dentry(name, NULL, 0);
-	error = PTR_ERR(dentry);
-	if (IS_ERR(dentry))
-		goto exit;
-
-	dir = dget(dentry->d_parent);
 
-	error = -ENOENT;
-	if (!dentry->d_inode)
-		goto exit;
-	/*
-	 * The dentry->d_count stuff confuses d_delete() enough to
-	 * not kill the inode from under us while it is locked. This
-	 * wouldn't be needed, except the dentry semaphore is really
-	 * in the inode, not in the dentry..
-	 */
-	dentry->d_count++;
-	double_lock(dir, dentry);
-	if (dentry->d_parent != dir)
-		goto exit_lock;
 
-	error = -EROFS;
-	if (IS_RDONLY(dir->d_inode))
-		goto exit_lock;
+int vfs_rmdir(struct inode *dir, struct dentry *dentry)
+{
+	int error;
 
-	error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC);
+	error = may_delete(dir, dentry, 1);
 	if (error)
-		goto exit_lock;
+		return error;
 
-	/*
-	 * A subdirectory cannot be removed from an append-only directory.
-	 */
-	error = -EPERM;
-	if (IS_APPEND(dir->d_inode))
-		goto exit_lock;
-
-	/* Disallow removals of mountpoints. */
-	error = -EBUSY;
-	if (dentry->d_mounts != dentry->d_covers)
-		goto exit_lock;
+	if (!dir->i_op || !dir->i_op->rmdir)
+		return -EPERM;
 
-	error = -EPERM;
-	if (!dir->d_inode->i_op || !dir->d_inode->i_op->rmdir)
-		goto exit_lock;
-
-	DQUOT_INIT(dir->d_inode);
+	DQUOT_INIT(dir);
 
 	/*
 	 * We try to drop the dentry early: we should have
@@ -942,11 +957,42 @@
 		d_drop(dentry);
 	}
 
-	error = dir->d_inode->i_op->rmdir(dir->d_inode, dentry);
+	error = dir->i_op->rmdir(dir, dentry);
+
+	return error;
+}
+
+static inline int do_rmdir(const char * name)
+{
+	int error;
+	struct dentry *dir;
+	struct dentry *dentry;
+
+	dentry = lookup_dentry(name, NULL, 0);
+	error = PTR_ERR(dentry);
+	if (IS_ERR(dentry))
+		goto exit;
+
+	error = -ENOENT;
+	if (!dentry->d_inode)
+		goto exit_dput;
+
+	dir = dget(dentry->d_parent);
+
+	/*
+	 * The dentry->d_count stuff confuses d_delete() enough to
+	 * not kill the inode from under us while it is locked. This
+	 * wouldn't be needed, except the dentry semaphore is really
+	 * in the inode, not in the dentry..
+	 */
+	dentry->d_count++;
+	double_lock(dir, dentry);
+
+	error = vfs_rmdir(dir->d_inode, dentry);
 
-exit_lock:
-	dentry->d_count--;
 	double_unlock(dentry, dir);
+exit_dput:
+	dput(dentry);
 exit:
 	return error;
 }
@@ -967,6 +1013,25 @@
 	return error;
 }
 
+int vfs_unlink(struct inode *dir, struct dentry *dentry)
+{
+	int error;
+
+	error = may_delete(dir, dentry, 0);
+	if (error)
+		goto exit_lock;
+
+	if (!dir->i_op || !dir->i_op->unlink)
+		goto exit_lock;
+
+	DQUOT_INIT(dir);
+
+	error = dir->i_op->unlink(dir, dentry);
+
+exit_lock:
+	return error;
+}
+
 static inline int do_unlink(const char * name)
 {
 	int error;
@@ -983,42 +1048,8 @@
 	if (IS_ERR(dir))
 		goto exit_dput;
 
-	error = -ENOENT;
-	if (!dentry->d_inode)
-		goto exit_lock;
-
-	/* Mount point? */
-	error = -EBUSY;
-	if (dentry == dir)
-		goto exit_lock;
-
-	error = -EROFS;
-	if (IS_RDONLY(dir->d_inode))
-		goto exit_lock;
-
-	error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC);
-	if (error)
-		goto exit_lock;
-
-	/*
-	 * A directory can't be unlink'ed.
-	 * A file cannot be removed from an append-only directory.
-	 */
-	error = -EPERM;
-	if (S_ISDIR(dentry->d_inode->i_mode))
-		goto exit_lock;
-
-	if (IS_APPEND(dir->d_inode))
-		goto exit_lock;
-
-	if (!dir->d_inode->i_op || !dir->d_inode->i_op->unlink)
-		goto exit_lock;
+	error = vfs_unlink(dir->d_inode, dentry);
 
-	DQUOT_INIT(dir->d_inode);
-
-	error = dir->d_inode->i_op->unlink(dir->d_inode, dentry);
-
-exit_lock:
         unlock_dir(dir);
 exit_dput:
 	dput(dentry);
@@ -1059,15 +1090,7 @@
 	if (IS_ERR(dir))
 		goto exit_dput;
 
-	error = -EEXIST;
-	if (dentry->d_inode)
-		goto exit_lock;
-
-	error = -EROFS;
-	if (IS_RDONLY(dir->d_inode))
-		goto exit_lock;
-
-	error = permission(dir->d_inode,MAY_WRITE | MAY_EXEC);
+	error = may_create(dir->d_inode, dentry);
 	if (error)
 		goto exit_lock;
 
@@ -1143,22 +1166,14 @@
 	if (!inode)
 		goto exit_lock;
 
-	error = -EEXIST;
-	if (new_dentry->d_inode)
-		goto exit_lock;
-
-	error = -EROFS;
-	if (IS_RDONLY(dir->d_inode))
+	error = may_create(dir->d_inode, new_dentry);
+	if (error)
 		goto exit_lock;
 
 	error = -EXDEV;
 	if (dir->d_inode->i_dev != inode->i_dev)
 		goto exit_lock;
 
-	error = permission(dir->d_inode, MAY_WRITE | MAY_EXEC);
-	if (error)
-		goto exit_lock;
-
 	/*
 	 * A link to an append-only or immutable file cannot be created.
 	 */
@@ -1205,6 +1220,38 @@
 	return error;
 }
 
+int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
+	       struct inode *new_dir, struct dentry *new_dentry)
+{
+	int error;
+	int isdir;
+
+	isdir = S_ISDIR(old_dentry->d_inode->i_mode);
+
+	error = may_delete(old_dir, old_dentry, isdir); /* XXX */
+	if (error)
+		return error;
+
+	if (new_dir->i_dev != old_dir->i_dev)
+		return -EXDEV;
+
+	if (!new_dentry->d_inode)
+		error = may_create(new_dir, new_dentry);
+	else
+		error = may_delete(new_dir, new_dentry, isdir);
+	if (error)
+		return error;
+
+	if (!old_dir->i_op || !old_dir->i_op->rename)
+		return -EPERM;
+
+	DQUOT_INIT(old_dir);
+	DQUOT_INIT(new_dir);
+	error = old_dir->i_op->rename(old_dir, old_dentry, new_dir, new_dentry);
+
+	return error;
+}
+
 static inline int do_rename(const char * oldname, const char * newname)
 {
 	int error;
@@ -1237,43 +1284,9 @@
 
 	double_lock(new_dir, old_dir);
 
-	error = permission(old_dir->d_inode,MAY_WRITE | MAY_EXEC);
-	if (error)
-		goto exit_lock;
-	error = permission(new_dir->d_inode,MAY_WRITE | MAY_EXEC);
-	if (error)
-		goto exit_lock;
-
-	/* Disallow moves of mountpoints. */
-	error = -EBUSY;
-	if (old_dir == old_dentry || new_dir == new_dentry)
-		goto exit_lock;
-
-	error = -EXDEV;
-	if (new_dir->d_inode->i_dev != old_dir->d_inode->i_dev)
-		goto exit_lock;
-
-	error = -EROFS;
-	if (IS_RDONLY(new_dir->d_inode) || IS_RDONLY(old_dir->d_inode))
-		goto exit_lock;
-
-	/*
-	 * A file cannot be removed from an append-only directory.
-	 */
-	error = -EPERM;
-	if (IS_APPEND(old_dir->d_inode))
-		goto exit_lock;
+	error = vfs_rename(old_dir->d_inode, old_dentry,
+			   new_dir->d_inode, new_dentry);
 
-	error = -EPERM;
-	if (!old_dir->d_inode->i_op || !old_dir->d_inode->i_op->rename)
-		goto exit_lock;
-
-	DQUOT_INIT(old_dir->d_inode);
-	DQUOT_INIT(new_dir->d_inode);
-	error = old_dir->d_inode->i_op->rename(old_dir->d_inode, old_dentry,
-					       new_dir->d_inode, new_dentry);
-
-exit_lock:
 	double_unlock(new_dir, old_dir);
 	dput(new_dentry);
 exit_old:
diff -u --recursive --new-file v2.1.131/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.1.131/linux/fs/nfs/dir.c	Wed Dec 16 10:32:55 1998
+++ linux/fs/nfs/dir.c	Wed Dec 16 12:17:22 1998
@@ -718,6 +718,9 @@
  *
  * 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)
 {
diff -u --recursive --new-file v2.1.131/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.1.131/linux/fs/nfs/inode.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/nfs/inode.c	Thu Dec 17 15:38:32 1998
@@ -597,8 +597,10 @@
 		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) {
@@ -624,7 +626,6 @@
 		if (sattr.size != fattr.size)
 			printk("nfs_notify_change: sattr=%d, fattr=%d??\n",
 				sattr.size, fattr.size);
-		nfs_truncate_dirty_pages(inode, sattr.size);
 		inode->i_size  = sattr.size;
 		inode->i_mtime = fattr.mtime.seconds;
 	}
@@ -749,52 +750,45 @@
 	if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
 		goto out_changed;
 
+	inode->i_mode = fattr->mode;
+	inode->i_nlink = fattr->nlink;
+	inode->i_uid = fattr->uid;
+	inode->i_gid = fattr->gid;
+
+	inode->i_blocks = fattr->blocks;
+	inode->i_atime = fattr->atime.seconds;
+	inode->i_ctime = fattr->ctime.seconds;
+
 	/*
-	 * If we have pending write-back entries, we don't want
-	 * to look at the size the server sends us too closely..
-	 * In particular, ignore the server if it tells us that
-	 * the file is smaller or older than we locally think it
-	 * is.. 
+	 * Update the read time so we don't revalidate too often.
 	 */
-	if (NFS_WRITEBACK(inode)) {
-		if (inode->i_size > fattr->size)
-			fattr->size = inode->i_size;
-		if (inode->i_mtime > fattr->mtime.seconds)
-			fattr->mtime.seconds = inode->i_mtime;
-	}
+	NFS_READTIME(inode) = jiffies;
+	error = 0;
 
 	/*
-	 * If the size or mtime changed from outside, we want
-	 * to invalidate the local caches immediately.
+	 * If we have pending write-back entries, we don't want
+	 * to look at the size or the mtime the server sends us
+	 * too closely, as we're in the middle of modifying them.
 	 */
+	if (NFS_WRITEBACK(inode))
+		goto out;
+
 	if (inode->i_size != fattr->size) {
 #ifdef NFS_DEBUG_VERBOSE
 printk("NFS: size change on %x/%ld\n", inode->i_dev, inode->i_ino);
 #endif
+		inode->i_size = fattr->size;
 		invalid = 1;
 	}
+
 	if (inode->i_mtime != fattr->mtime.seconds) {
 #ifdef NFS_DEBUG_VERBOSE
 printk("NFS: mtime change on %x/%ld\n", inode->i_dev, inode->i_ino);
 #endif
+		inode->i_mtime = fattr->mtime.seconds;
 		invalid = 1;
 	}
 
-	inode->i_mode = fattr->mode;
-	inode->i_nlink = fattr->nlink;
-	inode->i_uid = fattr->uid;
-	inode->i_gid = fattr->gid;
-
-	inode->i_size = fattr->size;
-	inode->i_blocks = fattr->blocks;
-	inode->i_atime = fattr->atime.seconds;
-	inode->i_mtime = fattr->mtime.seconds;
-	inode->i_ctime = fattr->ctime.seconds;
-	/*
-	 * Update the read time so we don't revalidate too often.
-	 */
-	NFS_READTIME(inode) = jiffies;
-	error = 0;
 	if (invalid)
 		goto out_invalid;
 out:
@@ -810,6 +804,7 @@
 #endif
 	fattr->mode = inode->i_mode; /* save mode */
 	make_bad_inode(inode);
+	nfs_inval(inode);
 	inode->i_mode = fattr->mode; /* restore mode */
 	/*
 	 * No need to worry about unhashing the dentry, as the
@@ -824,12 +819,9 @@
 #ifdef NFS_DEBUG_VERBOSE
 printk("nfs_refresh_inode: invalidating %ld pages\n", inode->i_nrpages);
 #endif
-	if (!S_ISDIR(inode->i_mode)) {
-		/* This sends off all dirty pages off to the server.
-		 * Note that this function must not sleep. */
-		nfs_inval(inode);
+	if (!S_ISDIR(inode->i_mode))
 		invalidate_inode_pages(inode);
-	} else
+	else
 		nfs_invalidate_dircache(inode);
 	NFS_CACHEINV(inode);
 	NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
diff -u --recursive --new-file v2.1.131/linux/fs/nfs/read.c linux/fs/nfs/read.c
--- v2.1.131/linux/fs/nfs/read.c	Thu Nov 19 09:56:28 1998
+++ linux/fs/nfs/read.c	Tue Dec 22 09:37:43 1998
@@ -229,6 +229,7 @@
 
 	dprintk("NFS: nfs_readpage (%p %ld@%ld)\n",
 		page, PAGE_SIZE, page->offset);
+	atomic_inc(&page->count);
 	set_bit(PG_locked, &page->flags);
 
 	/*
@@ -240,18 +241,24 @@
 	 */
 	error = nfs_wb_page(inode, page);
 	if (error)
-		return error;
+		goto out_error;
 
 	error = -1;
-	atomic_inc(&page->count);
 	if (!IS_SWAPFILE(inode) && !PageError(page) &&
 	    NFS_SERVER(inode)->rsize >= PAGE_SIZE)
 		error = nfs_readpage_async(dentry, inode, page);
-	if (error < 0) {	/* couldn't enqueue */
-		error = nfs_readpage_sync(dentry, inode, page);
-		if (error < 0 && IS_SWAPFILE(inode))
-			printk("Aiee.. nfs swap-in of page failed!\n");
-		free_page(page_address(page));
-	}
+	if (error >= 0)
+		goto out;
+
+	error = nfs_readpage_sync(dentry, inode, page);
+	if (error < 0 && IS_SWAPFILE(inode))
+		printk("Aiee.. nfs swap-in of page failed!\n");
+	goto out_free;
+
+out_error:
+	clear_bit(PG_locked, &page->flags);
+out_free:
+	free_page(page_address(page));
+out:
 	return error;
 }
diff -u --recursive --new-file v2.1.131/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.1.131/linux/fs/nfs/write.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/nfs/write.c	Thu Dec 17 15:54:25 1998
@@ -583,39 +583,22 @@
 	NFS_WB(inode, req->wb_pid == pid);
 }
 
-void
-nfs_inval(struct inode *inode)
-{
-	nfs_cancel_dirty(inode,0);
-}
-
 /*
- * Cancel any pending write requests after a given offset
- * (called from nfs_notify_change).
+ * 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_truncate_dirty_pages(struct inode *inode, unsigned long offset)
+nfs_flush_trunc(struct inode *inode, unsigned long from)
 {
-	struct nfs_wreq *req, *head;
-	unsigned long	rqoffset;
-
-	dprintk("NFS:      truncate_dirty_pages(%d/%ld, %ld)\n",
-		inode->i_dev, inode->i_ino, offset);
-
-	req = head = NFS_WRITEBACK(inode);
-	while (req != NULL) {
-		rqoffset = req->wb_page->offset + req->wb_offset;
-
-		if (rqoffset >= offset) {
-			nfs_cancel_request(req);
-		} else if (rqoffset + req->wb_bytes >= offset) {
-			req->wb_bytes = offset - rqoffset;
-		}
-		if ((req = WB_NEXT(req)) == head)
-			break;
-	}
+	from &= PAGE_MASK;
+	NFS_WB(inode, req->wb_page->offset >= from);
+}
 
-	return 0;
+void
+nfs_inval(struct inode *inode)
+{
+	nfs_cancel_dirty(inode,0);
 }
 
 /*
@@ -648,6 +631,7 @@
 	task->tk_status = 0;
 
 	/* Setup the task struct for a writeback call */
+	req->wb_flags |= NFS_WRITE_INPROGRESS;
 	req->wb_args.fh     = NFS_FH(dentry);
 	req->wb_args.offset = page->offset + req->wb_offset;
 	req->wb_args.count  = req->wb_bytes;
@@ -655,7 +639,6 @@
 
 	rpc_call_setup(task, NFSPROC_WRITE, &req->wb_args, &req->wb_fattr, 0);
 
-	req->wb_flags |= NFS_WRITE_INPROGRESS;
 	return;
 }
 
diff -u --recursive --new-file v2.1.131/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.1.131/linux/fs/nfsd/vfs.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/nfsd/vfs.c	Fri Dec 18 07:09:35 1998
@@ -996,13 +996,6 @@
 	    (tlen == 1 || (tlen == 2 && tname[1] == '.'))))
 		goto out;
 
-	err = -EXDEV;
-	if (fdir->i_dev != tdir->i_dev)
-		goto out_nfserr;
-	err = -EPERM;
-	if (!fdir->i_op || !fdir->i_op->rename)
-		goto out_nfserr;
-
 	odentry = lookup_dentry(fname, dget(fdentry), 0);
 	err = PTR_ERR(odentry);
 	if (IS_ERR(odentry))
@@ -1019,9 +1012,7 @@
 	nfsd_double_down(&tdir->i_sem, &fdir->i_sem);
 	/* N.B. check for parent changes after locking?? */
 
-	DQUOT_INIT(fdir);
-	DQUOT_INIT(tdir);
-	err = fdir->i_op->rename(fdir, odentry, tdir, ndentry);
+	err = vfs_rename(fdir, odentry, tdir, ndentry);
 	if (!err && EX_ISSYNC(tfhp->fh_export)) {
 		write_inode_now(fdir);
 		write_inode_now(tdir);
@@ -1072,29 +1063,43 @@
 	if (IS_ERR(rdentry))
 		goto out_nfserr;
 
-	/*
-	 * FIXME!!
-	 *
-	 * This should do a double-lock on both rdentry and the parent
-	 */
-	err = fh_lock_parent(fhp, rdentry);
-	if (err)
-		goto out;
+	if (type != S_IFDIR) {
+		/* It's UNLINK */
+		err = fh_lock_parent(fhp, rdentry);
+		if (err)
+			goto out;
+
+		err = vfs_unlink(dirp, rdentry);
+
+		DQUOT_DROP(dirp);
+		fh_unlock(fhp);
+
+		dput(rdentry);
 
-	DQUOT_INIT(dirp);
-	if (type == S_IFDIR) {
-		err = -ENOTDIR;
-		if (dirp->i_op && dirp->i_op->rmdir)
-			err = dirp->i_op->rmdir(dirp, rdentry);
 	} else {
-		err = -EPERM;
-		if (dirp->i_op && dirp->i_op->unlink)
-			err = dirp->i_op->unlink(dirp, rdentry);
+		/* It's RMDIR */
+		/* See comments in fs/namei.c:do_rmdir */
+		rdentry->d_count++;
+		nfsd_double_down(&dirp->i_sem, &rdentry->d_inode->i_sem);
+		if (!fhp->fh_pre_mtime)
+			fhp->fh_pre_mtime = dirp->i_mtime;
+		fhp->fh_locked = 1;
+		/* CHECKME: Should we do something with the child? */
+
+		err = -ENOENT;
+		if (rdentry->d_parent->d_inode == dirp)
+			err = vfs_rmdir(dirp, rdentry);
+
+		rdentry->d_count--;
+		DQUOT_DROP(dirp);
+		if (!fhp->fh_post_version)
+			fhp->fh_post_version = dirp->i_version;
+		fhp->fh_locked = 0;
+		nfsd_double_up(&dirp->i_sem, &rdentry->d_inode->i_sem);
+
+		dput(rdentry);
 	}
-	DQUOT_DROP(dirp);
-	fh_unlock(fhp);
 
-	dput(rdentry);
 	if (err)
 		goto out_nfserr;
 	if (EX_ISSYNC(fhp->fh_export))
diff -u --recursive --new-file v2.1.131/linux/fs/nls/Config.in linux/fs/nls/Config.in
--- v2.1.131/linux/fs/nls/Config.in	Mon Dec 29 10:22:46 1997
+++ linux/fs/nls/Config.in	Fri Dec 18 08:09:51 1998
@@ -13,31 +13,32 @@
 if [ "$CONFIG_NLS" = "y" ]; then
   mainmenu_option next_comment
   comment 'Native Language Support'
-  tristate 'Codepage 437'      CONFIG_NLS_CODEPAGE_437
-  tristate 'Codepage 737'      CONFIG_NLS_CODEPAGE_737
-  tristate 'Codepage 775'      CONFIG_NLS_CODEPAGE_775
-  tristate 'Codepage 850'      CONFIG_NLS_CODEPAGE_850
-  tristate 'Codepage 852'      CONFIG_NLS_CODEPAGE_852
-  tristate 'Codepage 855'      CONFIG_NLS_CODEPAGE_855
-  tristate 'Codepage 857'      CONFIG_NLS_CODEPAGE_857
-  tristate 'Codepage 860'      CONFIG_NLS_CODEPAGE_860
-  tristate 'Codepage 861'      CONFIG_NLS_CODEPAGE_861
-  tristate 'Codepage 862'      CONFIG_NLS_CODEPAGE_862
-  tristate 'Codepage 863'      CONFIG_NLS_CODEPAGE_863
-  tristate 'Codepage 864'      CONFIG_NLS_CODEPAGE_864
-  tristate 'Codepage 865'      CONFIG_NLS_CODEPAGE_865
-  tristate 'Codepage 866'      CONFIG_NLS_CODEPAGE_866
-  tristate 'Codepage 869'      CONFIG_NLS_CODEPAGE_869
-  tristate 'Codepage 874'      CONFIG_NLS_CODEPAGE_874
-  tristate 'NLS ISO 8859-1'    CONFIG_NLS_ISO8859_1
-  tristate 'NLS ISO 8859-2'    CONFIG_NLS_ISO8859_2
-  tristate 'NLS ISO 8859-3'    CONFIG_NLS_ISO8859_3
-  tristate 'NLS ISO 8859-4'    CONFIG_NLS_ISO8859_4
-  tristate 'NLS ISO 8859-5'    CONFIG_NLS_ISO8859_5
-  tristate 'NLS ISO 8859-6'    CONFIG_NLS_ISO8859_6
-  tristate 'NLS ISO 8859-7'    CONFIG_NLS_ISO8859_7
-  tristate 'NLS ISO 8859-8'    CONFIG_NLS_ISO8859_8
-  tristate 'NLS ISO 8859-9'    CONFIG_NLS_ISO8859_9
-  tristate 'NLS KOI8-R'        CONFIG_NLS_KOI8_R
+  tristate 'Codepage 437 (United States, Canada)'  CONFIG_NLS_CODEPAGE_437
+  tristate 'Codepage 737 (Greek)'                  CONFIG_NLS_CODEPAGE_737
+  tristate 'Codepage 775 (Baltic Rim)'             CONFIG_NLS_CODEPAGE_775
+  tristate 'Codepage 850 (Europe)'                 CONFIG_NLS_CODEPAGE_850
+  tristate 'Codepage 852 (Central/Eastern Europe)' CONFIG_NLS_CODEPAGE_852
+  tristate 'Codepage 855 (Cyrillic)'               CONFIG_NLS_CODEPAGE_855
+  tristate 'Codepage 857 (Turkish)'                CONFIG_NLS_CODEPAGE_857
+  tristate 'Codepage 860 (Portugese)'              CONFIG_NLS_CODEPAGE_860
+  tristate 'Codepage 861 (Icelandic)'              CONFIG_NLS_CODEPAGE_861
+  tristate 'Codepage 862 (Hebrew)'                 CONFIG_NLS_CODEPAGE_862
+  tristate 'Codepage 863 (Canadian French)'        CONFIG_NLS_CODEPAGE_863
+  tristate 'Codepage 864 (Arabic)'                 CONFIG_NLS_CODEPAGE_864
+  tristate 'Codepage 865 (Nordic European)'        CONFIG_NLS_CODEPAGE_865
+  tristate 'Codepage 866 (Cyrillic/Russian)'       CONFIG_NLS_CODEPAGE_866
+  tristate 'Codepage 869 (Greek)'                  CONFIG_NLS_CODEPAGE_869
+  tristate 'Codepage 874 (Thai)'                   CONFIG_NLS_CODEPAGE_874
+  tristate 'NLS ISO 8859-1  (Latin 1; Western European Languages)' CONFIG_NLS_ISO8859_1
+  tristate 'NLS ISO 8859-2  (Latin 2; Slavic/Central European)' CONFIG_NLS_ISO8859_2
+  tristate 'NLS ISO 8859-3  (Latin 3; Esperanto, Galician, Maltese, Turkish)' CONFIG_NLS_ISO8859_3
+  tristate 'NLS ISO 8859-4  (Latin 4; Estonian, Latvian, Lithuanian)' CONFIG_NLS_ISO8859_4
+  tristate 'NLS ISO 8859-5  (Cyrillic)'             CONFIG_NLS_ISO8859_5
+  tristate 'NLS ISO 8859-6  (Arabic)'               CONFIG_NLS_ISO8859_6
+  tristate 'NLS ISO 8859-7  (Modern Greek)'         CONFIG_NLS_ISO8859_7
+  tristate 'NLS ISO 8859-8  (Hebrew)'               CONFIG_NLS_ISO8859_8
+  tristate 'NLS ISO 8859-9  (Latin 5; Turkey)'      CONFIG_NLS_ISO8859_9
+  tristate 'NLS ISO 8859-15 (Latin 9; Western European with Euro)' CONFIG_NLS_ISO8859_15
+  tristate 'NLS KOI8-R (Russian)'                   CONFIG_NLS_KOI8_R
   endmenu
 fi
diff -u --recursive --new-file v2.1.131/linux/fs/nls/Makefile linux/fs/nls/Makefile
--- v2.1.131/linux/fs/nls/Makefile	Wed Oct 29 15:30:09 1997
+++ linux/fs/nls/Makefile	Fri Dec 18 08:09:51 1998
@@ -286,6 +286,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_NLS_ISO8859_15),y)
+NLS += nls_iso8859-15.o
+else
+  ifeq ($(CONFIG_NLS_ISO8859_15),m)
+  M_OBJS += nls_iso8859-15.o
+  endif
+endif
+
 ifeq ($(CONFIG_NLS_KOI8_R),y)
 NLS += nls_koi8-r.o
 else
diff -u --recursive --new-file v2.1.131/linux/fs/nls/nls_base.c linux/fs/nls/nls_base.c
--- v2.1.131/linux/fs/nls/nls_base.c	Sun Nov  8 14:03:07 1998
+++ linux/fs/nls/nls_base.c	Fri Dec 18 08:09:51 1998
@@ -429,6 +429,9 @@
 #ifdef CONFIG_NLS_ISO8859_9
 	init_nls_iso8859_9();
 #endif
+#ifdef CONFIG_NLS_ISO8859_15
+	init_nls_iso8859_15();
+#endif
 #ifdef CONFIG_NLS_CODEPAGE_437
 	init_nls_cp437();
 #endif
diff -u --recursive --new-file v2.1.131/linux/fs/nls/nls_iso8859-15.c linux/fs/nls/nls_iso8859-15.c
--- v2.1.131/linux/fs/nls/nls_iso8859-15.c	Wed Dec 31 16:00:00 1969
+++ linux/fs/nls/nls_iso8859-15.c	Fri Dec 18 08:09:51 1998
@@ -0,0 +1,268 @@
+/*
+ * linux/fs/nls_iso8859-15.c
+ *
+ * Charset iso8859-15 translation tables.
+ * The Unicode to charset table has only exact mappings.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/nls.h>
+
+static struct nls_unicode charset2uni[256] = {
+	/* 0x00*/
+	{0x00, 0x00}, {0x01, 0x00}, {0x02, 0x00}, {0x03, 0x00},
+	{0x04, 0x00}, {0x05, 0x00}, {0x06, 0x00}, {0x07, 0x00},
+	{0x08, 0x00}, {0x09, 0x00}, {0x0a, 0x00}, {0x0b, 0x00},
+	{0x0c, 0x00}, {0x0d, 0x00}, {0x0e, 0x00}, {0x0f, 0x00},
+	/* 0x10*/
+	{0x10, 0x00}, {0x11, 0x00}, {0x12, 0x00}, {0x13, 0x00},
+	{0x14, 0x00}, {0x15, 0x00}, {0x16, 0x00}, {0x17, 0x00},
+	{0x18, 0x00}, {0x19, 0x00}, {0x1a, 0x00}, {0x1b, 0x00},
+	{0x1c, 0x00}, {0x1d, 0x00}, {0x1e, 0x00}, {0x1f, 0x00},
+	/* 0x20*/
+	{0x20, 0x00}, {0x21, 0x00}, {0x22, 0x00}, {0x23, 0x00},
+	{0x24, 0x00}, {0x25, 0x00}, {0x26, 0x00}, {0x27, 0x00},
+	{0x28, 0x00}, {0x29, 0x00}, {0x2a, 0x00}, {0x2b, 0x00},
+	{0x2c, 0x00}, {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00},
+	/* 0x30*/
+	{0x30, 0x00}, {0x31, 0x00}, {0x32, 0x00}, {0x33, 0x00},
+	{0x34, 0x00}, {0x35, 0x00}, {0x36, 0x00}, {0x37, 0x00},
+	{0x38, 0x00}, {0x39, 0x00}, {0x3a, 0x00}, {0x3b, 0x00},
+	{0x3c, 0x00}, {0x3d, 0x00}, {0x3e, 0x00}, {0x3f, 0x00},
+	/* 0x40*/
+	{0x40, 0x00}, {0x41, 0x00}, {0x42, 0x00}, {0x43, 0x00},
+	{0x44, 0x00}, {0x45, 0x00}, {0x46, 0x00}, {0x47, 0x00},
+	{0x48, 0x00}, {0x49, 0x00}, {0x4a, 0x00}, {0x4b, 0x00},
+	{0x4c, 0x00}, {0x4d, 0x00}, {0x4e, 0x00}, {0x4f, 0x00},
+	/* 0x50*/
+	{0x50, 0x00}, {0x51, 0x00}, {0x52, 0x00}, {0x53, 0x00},
+	{0x54, 0x00}, {0x55, 0x00}, {0x56, 0x00}, {0x57, 0x00},
+	{0x58, 0x00}, {0x59, 0x00}, {0x5a, 0x00}, {0x5b, 0x00},
+	{0x5c, 0x00}, {0x5d, 0x00}, {0x5e, 0x00}, {0x5f, 0x00},
+	/* 0x60*/
+	{0x60, 0x00}, {0x61, 0x00}, {0x62, 0x00}, {0x63, 0x00},
+	{0x64, 0x00}, {0x65, 0x00}, {0x66, 0x00}, {0x67, 0x00},
+	{0x68, 0x00}, {0x69, 0x00}, {0x6a, 0x00}, {0x6b, 0x00},
+	{0x6c, 0x00}, {0x6d, 0x00}, {0x6e, 0x00}, {0x6f, 0x00},
+	/* 0x70*/
+	{0x70, 0x00}, {0x71, 0x00}, {0x72, 0x00}, {0x73, 0x00},
+	{0x74, 0x00}, {0x75, 0x00}, {0x76, 0x00}, {0x77, 0x00},
+	{0x78, 0x00}, {0x79, 0x00}, {0x7a, 0x00}, {0x7b, 0x00},
+	{0x7c, 0x00}, {0x7d, 0x00}, {0x7e, 0x00}, {0x7f, 0x00},
+	/* 0x80*/
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	/* 0x90*/
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	{0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00}, {0x00, 0x00},
+	/* 0xa0*/
+	{0xa0, 0x00}, {0xa1, 0x00}, {0xa2, 0x00}, {0xa3, 0x00},
+	{0xac, 0x20}, {0xa5, 0x00}, {0x60, 0x01}, {0xa7, 0x00},
+	{0x61, 0x01}, {0xa9, 0x00}, {0xaa, 0x00}, {0xab, 0x00},
+	{0xac, 0x00}, {0xad, 0x00}, {0xae, 0x00}, {0xaf, 0x00},
+	/* 0xb0*/
+	{0xb0, 0x00}, {0xb1, 0x00}, {0xb2, 0x00}, {0xb3, 0x00},
+	{0x7d, 0x01}, {0xb5, 0x00}, {0xb6, 0x00}, {0xb7, 0x00},
+	{0x7e, 0x01}, {0xb9, 0x00}, {0xba, 0x00}, {0xbb, 0x00},
+	{0x52, 0x01}, {0x53, 0x01}, {0x78, 0x01}, {0xbf, 0x00},
+	/* 0xc0*/
+	{0xc0, 0x00}, {0xc1, 0x00}, {0xc2, 0x00}, {0xc3, 0x00},
+	{0xc4, 0x00}, {0xc5, 0x00}, {0xc6, 0x00}, {0xc7, 0x00},
+	{0xc8, 0x00}, {0xc9, 0x00}, {0xca, 0x00}, {0xcb, 0x00},
+	{0xcc, 0x00}, {0xcd, 0x00}, {0xce, 0x00}, {0xcf, 0x00},
+	/* 0xd0*/
+	{0xd0, 0x00}, {0xd1, 0x00}, {0xd2, 0x00}, {0xd3, 0x00},
+	{0xd4, 0x00}, {0xd5, 0x00}, {0xd6, 0x00}, {0xd7, 0x00},
+	{0xd8, 0x00}, {0xd9, 0x00}, {0xda, 0x00}, {0xdb, 0x00},
+	{0xdc, 0x00}, {0xdd, 0x00}, {0xde, 0x00}, {0xdf, 0x00},
+	/* 0xe0*/
+	{0xe0, 0x00}, {0xe1, 0x00}, {0xe2, 0x00}, {0xe3, 0x00},
+	{0xe4, 0x00}, {0xe5, 0x00}, {0xe6, 0x00}, {0xe7, 0x00},
+	{0xe8, 0x00}, {0xe9, 0x00}, {0xea, 0x00}, {0xeb, 0x00},
+	{0xec, 0x00}, {0xed, 0x00}, {0xee, 0x00}, {0xef, 0x00},
+	/* 0xf0*/
+	{0xf0, 0x00}, {0xf1, 0x00}, {0xf2, 0x00}, {0xf3, 0x00},
+	{0xf4, 0x00}, {0xf5, 0x00}, {0xf6, 0x00}, {0xf7, 0x00},
+	{0xf8, 0x00}, {0xf9, 0x00}, {0xfa, 0x00}, {0xfb, 0x00},
+	{0xfc, 0x00}, {0xfd, 0x00}, {0xfe, 0x00}, {0xff, 0x00},
+};
+
+static unsigned char page00[256] = {
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* 0x00-0x07 */
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /* 0x08-0x0f */
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, /* 0x10-0x17 */
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, /* 0x18-0x1f */
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, /* 0x20-0x27 */
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, /* 0x28-0x2f */
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, /* 0x30-0x37 */
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, /* 0x38-0x3f */
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, /* 0x40-0x47 */
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, /* 0x48-0x4f */
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, /* 0x50-0x57 */
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, /* 0x58-0x5f */
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, /* 0x60-0x67 */
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, /* 0x68-0x6f */
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, /* 0x70-0x77 */
+	0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0xa0, 0xa1, 0xa2, 0xa3, 0x00, 0xa5, 0x00, 0xa7, /* 0xa0-0xa7 */
+	0x00, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* 0xa8-0xaf */
+	0xb0, 0xb1, 0xb2, 0xb3, 0x00, 0xb5, 0xb6, 0xb7, /* 0xb0-0xb7 */
+	0x00, 0xb9, 0xba, 0xbb, 0x00, 0x00, 0x00, 0xbf, /* 0xb8-0xbf */
+	0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* 0xc0-0xc7 */
+	0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* 0xc8-0xcf */
+	0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, /* 0xd0-0xd7 */
+	0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, /* 0xd8-0xdf */
+	0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, /* 0xe0-0xe7 */
+	0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /* 0xe8-0xef */
+	0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, /* 0xf0-0xf7 */
+	0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff, /* 0xf8-0xff */
+};
+
+static unsigned char page01[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0x00, 0x00, 0xbc, 0xbd, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+	0xa6, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0xbe, 0x00, 0x00, 0x00, 0x00, 0xb4, 0xb8, 0x00, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char page20[256] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00-0x07 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x08-0x0f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10-0x17 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x18-0x1f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20-0x27 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x28-0x2f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30-0x37 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x38-0x3f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x40-0x47 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x48-0x4f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x50-0x57 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x58-0x5f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60-0x67 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x68-0x6f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70-0x77 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x78-0x7f */
+
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x80-0x87 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x88-0x8f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x90-0x97 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x98-0x9f */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa0-0xa7 */
+	0x00, 0x00, 0x00, 0x00, 0xa4, 0x00, 0x00, 0x00, /* 0xa8-0xaf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb0-0xb7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb8-0xbf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0-0xc7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc8-0xcf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0-0xd7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd8-0xdf */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe0-0xe7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe8-0xef */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf0-0xf7 */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf8-0xff */
+};
+
+static unsigned char *page_uni2charset[256] = {
+	page00, page01,	NULL,   NULL,   NULL,   NULL,   NULL,   NULL,   
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+
+	page20,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,	NULL,
+};
+
+static void inc_use_count(void)
+{
+	MOD_INC_USE_COUNT;
+}
+
+static void dec_use_count(void)
+{
+	MOD_DEC_USE_COUNT;
+}
+
+static struct nls_table table = {
+	"iso8859-15",
+	page_uni2charset,
+	charset2uni,
+	inc_use_count,
+	dec_use_count,
+	NULL
+};
+
+int init_nls_iso8859_15(void)
+{
+	return register_nls(&table);
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+	return init_nls_iso8859_15();
+}
+
+
+void cleanup_module(void)
+{
+	unregister_nls(&table);
+	return;
+}
+#endif
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 8
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -8
+ * c-argdecl-indent: 8
+ * c-label-offset: -8
+ * c-continued-statement-offset: 8
+ * c-continued-brace-offset: 0
+ * End:
+ */
diff -u --recursive --new-file v2.1.131/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.1.131/linux/fs/proc/array.c	Fri Nov 27 13:09:28 1998
+++ linux/fs/proc/array.c	Sun Dec 20 05:52:02 1998
@@ -60,6 +60,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/swap.h>
+#include <linux/swapctl.h>
 #include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/signal.h>
@@ -371,6 +372,28 @@
 		i.freeswap >> 10);
 }
 
+static int get_swapstats(char * buffer)
+{
+	unsigned long *w = swapstats.kswap_wakeups;
+	
+	return sprintf(buffer,
+		       "ProcFreeTry:    %8lu\n"
+		       "ProcFreeSucc:   %8lu\n"
+		       "ProcShrinkTry:  %8lu\n"
+		       "ProcShrinkSucc: %8lu\n"
+		       "KswapFreeTry:   %8lu\n"
+		       "KswapFreeSucc:  %8lu\n"
+		       "KswapWakeups:	%8lu %lu %lu %lu\n",
+		       swapstats.gfp_freepage_attempts,
+		       swapstats.gfp_freepage_successes,
+		       swapstats.gfp_shrink_attempts,
+		       swapstats.gfp_shrink_successes,
+		       swapstats.kswap_freepage_attempts,
+		       swapstats.kswap_freepage_successes,
+		       w[0], w[1], w[2], w[3]
+		       );
+}
+
 static int get_version(char * buffer)
 {
 	extern char *linux_banner;
@@ -1257,6 +1280,9 @@
 		case PROC_MEMINFO:
 			return get_meminfo(page);
 
+		case PROC_SWAPSTATS:
+			return get_swapstats(page);
+
 #ifdef CONFIG_PCI_OLD_PROC
   	        case PROC_PCI:
 			return get_pci_list(page);
@@ -1342,7 +1368,7 @@
 static int process_unauthorized(int type, int pid)
 {
 	struct task_struct *p;
-	uid_t euid;	/* Save the euid keep the lock short */
+	uid_t euid=0;	/* Save the euid keep the lock short */
 		
 	read_lock(&tasklist_lock);
 	
diff -u --recursive --new-file v2.1.131/linux/fs/proc/root.c linux/fs/proc/root.c
--- v2.1.131/linux/fs/proc/root.c	Thu Nov 19 09:56:29 1998
+++ linux/fs/proc/root.c	Sun Dec 20 05:51:07 1998
@@ -493,6 +493,11 @@
 	S_IFREG | S_IRUGO, 1, 0, 0,
 	0, &proc_array_inode_operations
 };
+static struct proc_dir_entry proc_root_swapstats = {
+	PROC_SWAPSTATS, 9, "swapstats",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_array_inode_operations
+};
 static struct proc_dir_entry proc_root_kmsg = {
 	PROC_KMSG, 4, "kmsg",
 	S_IFREG | S_IRUSR, 1, 0, 0,
@@ -648,6 +653,7 @@
 	proc_register(&proc_root, &proc_root_loadavg);
 	proc_register(&proc_root, &proc_root_uptime);
 	proc_register(&proc_root, &proc_root_meminfo);
+	proc_register(&proc_root, &proc_root_swapstats);
 	proc_register(&proc_root, &proc_root_kmsg);
 	proc_register(&proc_root, &proc_root_version);
 	proc_register(&proc_root, &proc_root_cpuinfo);
diff -u --recursive --new-file v2.1.131/linux/fs/qnx4/namei.c linux/fs/qnx4/namei.c
--- v2.1.131/linux/fs/qnx4/namei.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/qnx4/namei.c	Fri Dec 18 07:09:35 1998
@@ -168,29 +168,9 @@
 	if (bh == NULL) {
 		return -ENOENT;
 	}
-	if ((inode = iget(dir->i_sb, ino)) == NULL) {
-		QNX4DEBUG(("qnx4: lookup->iget -> NULL\n"));
-		retval = -EACCES;
-		goto end_rmdir;
-	}
-	retval = -EPERM;
-	if ((dir->i_mode & S_ISVTX) &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER)) {
-		QNX4DEBUG(("qnx4: rmdir->capabilities\n"));
-		goto end_rmdir;
-	}
-	if (inode->i_dev != dir->i_dev) {
-		QNX4DEBUG(("qnx4: rmdir->different devices\n"));
-		goto end_rmdir;
-	}
-	if (inode == dir) {	/* we may not delete ".", but "../dir" is ok */
-		QNX4DEBUG(("qnx4: inode==dir\n"));
-		goto end_rmdir;
-	}
-	if (!S_ISDIR(inode->i_mode)) {
-		QNX4DEBUG(("qnx4: rmdir->not a directory\n"));
-		retval = -ENOTDIR;
+	inode = dentry->d_inode;
+	if (inode->i_ino != ino) {
+		retval = -EIO;
 		goto end_rmdir;
 	}
 #if 0
@@ -239,17 +219,12 @@
 	if (bh == NULL) {
 		return -ENOENT;
 	}
-	if ((inode = iget(dir->i_sb, ino)) == NULL) {
-		QNX4DEBUG(("qnx4: lookup->iget -> NULL\n"));
-		retval = -EACCES;
+	inode = dentry->d_inode;
+	if (inode->i_ino != ino) {
+		retval = -EIO;
 		goto end_unlink;
 	}
 	retval = -EPERM;
-	if ((dir->i_mode & S_ISVTX) &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER)) {
-		goto end_unlink;
-	}
 	if (!inode->i_nlink) {
 		QNX4DEBUG(("Deleting nonexistent file (%s:%lu), %d\n",
 			   kdevname(inode->i_dev),
diff -u --recursive --new-file v2.1.131/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.1.131/linux/fs/smbfs/dir.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/smbfs/dir.c	Wed Dec 16 12:17:22 1998
@@ -469,10 +469,6 @@
 	struct inode *inode = dentry->d_inode;
 	int error;
 
-	error = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto out;
-
 	/*
 	 * Close the directory if it's open.
 	 */
diff -u --recursive --new-file v2.1.131/linux/fs/sysv/CHANGES linux/fs/sysv/CHANGES
--- v2.1.131/linux/fs/sysv/CHANGES	Wed Jul  1 19:38:56 1998
+++ linux/fs/sysv/CHANGES	Fri Dec 18 07:09:35 1998
@@ -18,3 +18,23 @@
 Wed Feb  4 1998   Krzysztof G. Baranowski <kgb@manjak.knm.org.pl>
 	*    namei.c: removed static subdir(); is_subdir() from dcache.c
 		      is used instead. Cosmetic changes.
+
+Thu Dec  3 1998   Al Viro (viro@math.psu.edu)
+	*    namei.c (sysv_rmdir):
+		      Bugectomy: old check for victim being busy
+		      (inode->i_count) wasn't replaced (with checking
+		      dentry->d_count) and escaped Linus in the last round
+		      of changes. Shot and buried.
+
+Wed Dec  9 1998   AV
+	*    namei.c (do_sysv_rename):
+		       Fixed incorrect check for other owners + race.
+		       Removed checks that went to VFS.
+	*    namei.c (sysv_unlink):
+		       Removed checks that went to VFS.
+
+Thu Dec 10 1998   AV
+	*    namei.c (do_mknod):
+			Removed dead code - mknod is never asked to
+			create a symlink or directory. Incidentially,
+			it wouldn't do it right if it would be called.
diff -u --recursive --new-file v2.1.131/linux/fs/sysv/namei.c linux/fs/sysv/namei.c
--- v2.1.131/linux/fs/sysv/namei.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/sysv/namei.c	Fri Dec 18 07:09:35 1998
@@ -254,13 +254,6 @@
 	inode->i_op = NULL;
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &sysv_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &sysv_dir_inode_operations;
-		if (dir->i_mode & S_ISGID)
-			inode->i_mode |= S_ISGID;
-	}
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &sysv_symlink_inode_operations;
 	else if (S_ISCHR(inode->i_mode))
 		inode->i_op = &chrdev_inode_operations;
 	else if (S_ISBLK(inode->i_mode))
@@ -416,21 +409,8 @@
 	retval = -ENOENT;
 	if (!bh)
 		goto end_rmdir;
-	retval = -EPERM;
 	inode = dentry->d_inode;
 
-        if ((dir->i_mode & S_ISVTX) &&
-            current->fsuid != inode->i_uid &&
-            current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rmdir;
-	if (inode->i_dev != dir->i_dev)
-		goto end_rmdir;
-	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-		goto end_rmdir;
-	if (!S_ISDIR(inode->i_mode)) {
-		retval = -ENOTDIR;
-		goto end_rmdir;
-	}
 	if (!empty_dir(inode)) {
 		retval = -ENOTEMPTY;
 		goto end_rmdir;
@@ -439,7 +419,7 @@
 		retval = -ENOENT;
 		goto end_rmdir;
 	}
-	if (inode->i_count > 1) {
+	if (!list_empty(&dentry->d_hash)) {
 		retval = -EBUSY;
 		goto end_rmdir;
 	}
@@ -482,10 +462,6 @@
 		schedule();
 		goto repeat;
 	}
-	if ((dir->i_mode & S_ISVTX) &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !capable(CAP_FOWNER))
-		goto end_unlink;
 	if (de->inode != inode->i_ino) {
 		retval = -ENOENT;
 		goto end_unlink;
@@ -641,10 +617,6 @@
 		goto end_rename;
 	old_inode = old_dentry->d_inode;	/* don't cross mnt-points */
 	retval = -EPERM;
-	if ((old_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != old_inode->i_uid &&
-	    current->fsuid != old_dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rename;
 	new_inode = new_dentry->d_inode;
 	new_bh = sysv_find_entry(new_dir, new_dentry->d_name.name,
 				new_dentry->d_name.len, &new_de);
@@ -658,32 +630,20 @@
 		retval = 0;
 		goto end_rename;
 	}
-	if (new_inode && S_ISDIR(new_inode->i_mode)) {
-		retval = -EISDIR;
-		if (!S_ISDIR(old_inode->i_mode))
-			goto end_rename;
-		retval = -EINVAL;
-		if (is_subdir(new_dentry, old_dentry))
-			goto end_rename;
-		retval = -ENOTEMPTY;
-		if (!empty_dir(new_inode))
-			goto end_rename;
-		retval = -EBUSY;
-		if (new_inode->i_count > 1)
-			goto end_rename;
-	}
-	retval = -EPERM;
-	if (new_inode && (new_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != new_inode->i_uid &&
-	    current->fsuid != new_dir->i_uid && !capable(CAP_FOWNER))
-		goto end_rename;
 	if (S_ISDIR(old_inode->i_mode)) {
-		retval = -ENOTDIR;
-		if (new_inode && !S_ISDIR(new_inode->i_mode))
-			goto end_rename;
 		retval = -EINVAL;
 		if (is_subdir(new_dentry, old_dentry))
 			goto end_rename;
+		if (new_inode) {
+			if (new_dentry->d_count > 1)
+				shrink_dcache_parent(new_dentry);
+			retval = -EBUSY;
+			if (new_dentry->d_count > 1)
+				goto end_rename;
+			retval = -ENOTEMPTY;
+			if (!empty_dir(new_inode))
+				goto end_rename;
+		}
 		retval = -EIO;
 		dir_bh = sysv_file_bread(old_inode, 0, 0);
 		if (!dir_bh)
diff -u --recursive --new-file v2.1.131/linux/fs/ufs/namei.c linux/fs/ufs/namei.c
--- v2.1.131/linux/fs/ufs/namei.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/ufs/namei.c	Fri Dec 18 07:09:35 1998
@@ -475,13 +475,6 @@
 	inode->i_op = NULL;
 	if (S_ISREG(inode->i_mode))
 		inode->i_op = &ufs_file_inode_operations;
-	else if (S_ISDIR(inode->i_mode)) {
-		inode->i_op = &ufs_dir_inode_operations;
-		if (dir->i_mode & S_ISGID)
-			inode->i_mode |= S_ISGID;
-	}
-	else if (S_ISLNK(inode->i_mode))
-		inode->i_op = &ufs_symlink_inode_operations;
 	else if (S_ISCHR(inode->i_mode))
 		inode->i_op = &chrdev_inode_operations;
 	else if (S_ISBLK(inode->i_mode))
@@ -683,46 +676,15 @@
 	if (inode->i_sb->dq_op)
 		inode->i_sb->dq_op->initialize (inode, -1);
 
-	retval = -EPERM;
-	if ((dir->i_mode & S_ISVTX) && 
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !fsuser())
-		goto end_rmdir;
-	if (inode == dir)	/* we may not delete ".", but "../dir" is ok */
-		goto end_rmdir;
-
-	retval = -ENOTDIR;
-	if (!S_ISDIR(inode->i_mode))
-		goto end_rmdir;
-
 	retval = -EIO;
-	if (inode->i_dev != dir->i_dev)
-		goto end_rmdir;
 	if (SWAB32(de->d_ino) != inode->i_ino)
 		goto end_rmdir;
 
-	/*
-	 * Prune any child dentries so that this dentry becomes negative.
-	 */
-	if (dentry->d_count > 1) {
-		ufs_warning (sb, "ufs_rmdir", "d_count=%d, pruning\n", dentry->d_count);
-		shrink_dcache_parent(dentry);
-	}
 	if (!ufs_empty_dir (inode))
 		retval = -ENOTEMPTY;
 	else if (SWAB32(de->d_ino) != inode->i_ino)
 		retval = -ENOENT;
 	else {
-		if (dentry->d_count > 1) {
-		/*
-		 * Are we deleting the last instance of a busy directory?
-		 * Better clean up if so.
-		 *
-		 * Make directory empty (it will be truncated when finally
-		 * dereferenced).  This also inhibits ufs_add_entry.
-		 */
-			inode->i_size = 0;
-		}
 		retval = ufs_delete_entry (dir, de, bh);
 		dir->i_version = ++event;
 	}
@@ -739,6 +701,7 @@
 			      inode->i_nlink);
 	inode->i_version = ++event;
 	inode->i_nlink = 0;
+	inode->i_size = 0;
 	mark_inode_dirty(inode);
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
@@ -781,14 +744,6 @@
 	if (inode->i_sb->dq_op)
 		inode->i_sb->dq_op->initialize (inode, -1);
 
-	retval = -EPERM;
-	if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
-		goto end_unlink;
-	if ((dir->i_mode & S_ISVTX) &&
-	    current->fsuid != inode->i_uid &&
-	    current->fsuid != dir->i_uid && !fsuser())
-		goto end_unlink;
-
 	retval = -EIO;
 	if (SWAB32(de->d_ino) != inode->i_ino)
 		goto end_unlink;
@@ -988,20 +943,13 @@
 	old_bh = ufs_find_entry (old_dir, old_dentry->d_name.name, old_dentry->d_name.len, &old_de);
 	UFSD(("ino %u, reclen %u, namlen %u, name %s\n", SWAB32(old_de->d_ino),
 		SWAB16(old_de->d_reclen), ufs_get_de_namlen(old_de), old_de->d_name))
-	    
+
+	/* Arrrgh. See comments in ext2 */
 	retval = -ENOENT;
-	if (!old_bh)
+	if (!old_bh || SWAB32(old_de->d_ino) != old_inode->i_ino)
 		goto end_rename;
 	old_inode = old_dentry->d_inode;
 
-	retval = -EPERM;
-	if ((old_dir->i_mode & S_ISVTX) && 
-	    current->fsuid != old_inode->i_uid &&
-	    current->fsuid != old_dir->i_uid && !fsuser())
-		goto end_rename;
-	if (IS_APPEND(old_inode) || IS_IMMUTABLE(old_inode))
-		goto end_rename;
-
 	new_inode = new_dentry->d_inode;
 	UFSD(("name %s, len %u\n", new_dentry->d_name.name, new_dentry->d_name.len)) 
 	new_bh = ufs_find_entry (new_dir, new_dentry->d_name.name, new_dentry->d_name.len, &new_de);
@@ -1017,36 +965,21 @@
 	retval = 0;
 	if (new_inode == old_inode)
 		goto end_rename;
-	if (new_inode && S_ISDIR(new_inode->i_mode)) {
-		retval = -EISDIR;
-		if (!S_ISDIR(old_inode->i_mode))
-			goto end_rename;
-		retval = -EINVAL;
-		if (is_subdir(new_dentry, old_dentry))
-			goto end_rename;
-		retval = -ENOTEMPTY;
-		if (!ufs_empty_dir (new_inode))
-			goto end_rename;
-		retval = -EBUSY;
-		if (new_dentry->d_count > 1)
-			goto end_rename;
-	}
-	retval = -EPERM;
-	if (new_inode) {
-		if ((new_dir->i_mode & S_ISVTX) &&
-		    current->fsuid != new_inode->i_uid &&
-		    current->fsuid != new_dir->i_uid && !fsuser())
-			goto end_rename;
-		if (IS_APPEND(new_inode) || IS_IMMUTABLE(new_inode))
-			goto end_rename;
-	}
 	if (S_ISDIR(old_inode->i_mode)) {
-		retval = -ENOTDIR;
-		if (new_inode && !S_ISDIR(new_inode->i_mode))
-			goto end_rename;
 		retval = -EINVAL;
 		if (is_subdir(new_dentry, old_dentry))
 			goto end_rename;
+		if (new_inode) {
+			if (new_dentry->d_count > 1)
+				shrink_dcache_parent(new_dentry);
+			retval = -EBUSY;
+			if (new_dentry->d_count > 1)
+				goto end_rename;
+			retval = -ENOTEMPTY;
+			if (!ufs_empty_dir (new_inode))
+				goto end_rename;
+		}
+
 		dir_bh = ufs_bread (old_inode, 0, 0, &retval);
 		if (!dir_bh)
 			goto end_rename;
diff -u --recursive --new-file v2.1.131/linux/fs/umsdos/check.c linux/fs/umsdos/check.c
--- v2.1.131/linux/fs/umsdos/check.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/umsdos/check.c	Fri Dec 18 07:09:36 1998
@@ -108,7 +108,7 @@
 		} else if (inode->i_op == &umsdos_symlink_inode_operations) {
 			printk (" (i_op is umsdos_symlink_inode_operations)\n");
 		} else {
-			printk ((" (i_op is UNKNOWN: %p)\n", inode->i_op));
+			printk (" (i_op is UNKNOWN: %p)\n", inode->i_op);
 		}
 	} else {
 		printk (KERN_DEBUG "*   inode is NULL\n");
diff -u --recursive --new-file v2.1.131/linux/fs/umsdos/mangle.c linux/fs/umsdos/mangle.c
--- v2.1.131/linux/fs/umsdos/mangle.c	Thu Sep 17 17:53:38 1998
+++ linux/fs/umsdos/mangle.c	Thu Dec 17 09:05:42 1998
@@ -69,14 +69,8 @@
 		 * ever think of using such a name in real life. This is not
 		 * fool proof. I don't think there is a total solution to this.
 		 */
-		union {
-			int entry_num;
-			struct {
-				unsigned num1:5, num2:5, num3:5;
-			} num;
-		} u;
+		int entry_num;
 		char *pt = info->fake.fname + info->fake.len;
-
 		/* lookup for encoding the last character of the extension 
 		 * It contains valid character after the ugly one to make sure 
 		 * even if someone overflows the 32 * 32 * 9 limit, it still 
@@ -93,17 +87,17 @@
 		};
 
 #define lookup12 (lookup3+9)
-		u.entry_num = info->f_pos / UMSDOS_REC_SIZE;
-		if (u.entry_num > (9 * 32 * 32)) {
+		entry_num = info->f_pos / UMSDOS_REC_SIZE;
+		if (entry_num > (9* 32 * 32)){
 			printk (KERN_WARNING "UMSDOS: more than 9216 files in a directory.\n"
 				"This may break the mangling strategy.\n"
 				"Not a killer problem. See doc.\n");
 		}
 		*pt++ = '.';
-		*pt++ = lookup3[u.num.num3];
-		*pt++ = lookup12[u.num.num2];
-		*pt++ = lookup12[u.num.num1];
-		*pt = '\0';	/* help doing printk */
+		*pt++ = lookup3 [(entry_num >> 10) & 31];
+		*pt++ = lookup12[(entry_num >> 5) & 31];
+		*pt++ = lookup12[entry_num & 31];
+		*pt = '\0';		/* help doing printk */	
 		info->fake.len += 4;
 		info->msdos_reject = 0;		/* Avoid mangling twice */
 	}
diff -u --recursive --new-file v2.1.131/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c
--- v2.1.131/linux/fs/umsdos/namei.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/umsdos/namei.c	Wed Dec 16 12:17:22 1998
@@ -1011,14 +1011,6 @@
 	if (!list_empty(&dentry->d_hash))
 		goto out;
 
-	/* check the sticky bit */
-	ret = -EPERM;
-	if (is_sticky(dir, dentry->d_inode->i_uid)) {
-printk("umsdos_rmdir: %s/%s is sticky\n",
-dentry->d_parent->d_name.name, dentry->d_name.name);
-		goto out;
-	}
-
 	/* check whether the EMD is empty */
 	ret = -ENOTEMPTY;
 	empty = umsdos_isempty (dentry);
diff -u --recursive --new-file v2.1.131/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.1.131/linux/fs/vfat/namei.c	Wed Dec 16 10:32:56 1998
+++ linux/fs/vfat/namei.c	Fri Dec 18 07:09:36 1998
@@ -1416,12 +1416,6 @@
 	struct super_block *sb = dir->i_sb;
 	int res;
 
-	if (!S_ISDIR(dentry->d_inode->i_mode)) {
-		return -ENOTDIR;
-	}
-	if (dir->i_dev != dentry->d_inode->i_dev || dir == dentry->d_inode) {
-		return -EBUSY;
-	}
 	if (!list_empty(&dentry->d_hash))
 		return -EBUSY;
 
@@ -1814,6 +1808,10 @@
 
 	if (res == 0) {
 		drop_replace_inodes(old_dentry, new_inode);
+		list_del(&old_dentry->d_alias);
+		iput(old_dentry->d_inode);
+		d_instantiate(old_dentry, new_inode);
+
 		d_move(old_dentry, new_dentry);
 		put_new_inode = 0;
 	}
diff -u --recursive --new-file v2.1.131/linux/include/asm-alpha/dma.h linux/include/asm-alpha/dma.h
--- v2.1.131/linux/include/asm-alpha/dma.h	Fri Oct 23 22:01:22 1998
+++ linux/include/asm-alpha/dma.h	Wed Dec 16 13:35:49 1998
@@ -342,5 +342,13 @@
 #define KERNEL_HAVE_CHECK_DMA
 extern int check_dma(unsigned int dmanr);
 
+/* From PCI */
+
+#ifdef CONFIG_PCI_QUIRKS
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
+
 
 #endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.1.131/linux/include/asm-alpha/irq.h linux/include/asm-alpha/irq.h
--- v2.1.131/linux/include/asm-alpha/irq.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-alpha/irq.h	Tue Dec 22 08:22:39 1998
@@ -93,4 +93,7 @@
 extern void disable_irq(unsigned int);
 extern void enable_irq(unsigned int);
 
+extern void (*perf_irq)(unsigned long, struct pt_regs *);
+
+
 #endif /* _ALPHA_IRQ_H */
diff -u --recursive --new-file v2.1.131/linux/include/asm-alpha/system.h linux/include/asm-alpha/system.h
--- v2.1.131/linux/include/asm-alpha/system.h	Fri Oct 23 22:01:22 1998
+++ linux/include/asm-alpha/system.h	Tue Dec 22 08:22:39 1998
@@ -116,6 +116,24 @@
 #define draina() \
 __asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
 
+
+static inline unsigned long 
+wrperfmon(unsigned long perf_fun, unsigned long arg)
+{
+          register unsigned long __r0 __asm__("$0");
+	  register unsigned long __r16 __asm__("$16");
+	  register unsigned long __r17 __asm__("$17");
+	  __r16 = perf_fun;
+	  __r17 = arg;
+	  __asm__ __volatile__(
+		  "call_pal %1"
+		  : "=r"(__r0)
+		  : "i"(PAL_wrperfmon), "r"(__r16), "r"(__r17)
+		  : "$1", "$22", "$23", "$24", "$25", "$26");
+	  return __r0;
+}
+
+
 #define call_pal1(palno,arg)						\
 ({									\
 	register unsigned long __r0 __asm__("$0");			\
diff -u --recursive --new-file v2.1.131/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v2.1.131/linux/include/asm-alpha/termios.h	Mon Oct  5 13:13:42 1998
+++ linux/include/asm-alpha/termios.h	Wed Dec 16 13:35:49 1998
@@ -77,6 +77,8 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 /*	eof=^D		eol=\0		eol2=\0		erase=del
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-arc/dma.h linux/include/asm-arm/arch-arc/dma.h
--- v2.1.131/linux/include/asm-arm/arch-arc/dma.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/dma.h	Thu Dec 17 09:05:42 1998
@@ -24,14 +24,19 @@
 	DMA_MODE_WRITE
 } dmamode_t;
 
-#define MAX_DMA_CHANNELS	4
+#ifdef CONFIG_ARCH_ARC
+#define MAX_DMA_CHANNELS	3
 
-#define DMA_0			0
-#define DMA_1			1
-#define DMA_VIRTUAL_FLOPPY	2
-#define DMA_VIRTUAL_SOUND	3
+#define DMA_VIRTUAL_FLOPPY0	0
+#define DMA_VIRTUAL_FLOPPY1	1
+#define DMA_VIRTUAL_SOUND	2
+#endif
 
 #ifdef CONFIG_ARCH_A5K
+#define MAX_DMA_CHANNELS	2
+
+#define DMA_VIRTUAL_FLOPPY	0
+#define DMA_VIRTUAL_SOUND	1
 #define DMA_FLOPPY		DMA_VIRTUAL_FLOPPY
 #endif
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-arc/hardware.h linux/include/asm-arm/arch-arc/hardware.h
--- v2.1.131/linux/include/asm-arm/arch-arc/hardware.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/hardware.h	Thu Dec 17 09:05:42 1998
@@ -24,29 +24,45 @@
 #define HAS_MEMC1A
 #define HAS_VIDC
 
-#ifdef CONFIG_ARCH_A5K
-#define HAS_PCIO
-#endif
-
 /*
  * Optional hardware
  */
 #define HAS_EXPMASK
 
+/* Hardware addresses of major areas.
+ *  *_START is the physical address
+ *  *_SIZE  is the size of the region
+ *  *_BASE  is the virtual address
+ */
+#define IO_START		0x03000000
+#define IO_SIZE			0x01000000
+#define IO_BASE			0x03000000
+
+/*
+ * Screen mapping information
+ */
+#define SCREEN_START		0x02000000
+#define SCREEN2_END		0x02078000
+#define SCREEN2_BASE		0x02000000
+#define SCREEN1_END		0x02000000
+#define SCREEN1_BASE		0x01f88000
+
+
 #ifndef __ASSEMBLER__
 
 /*
  * for use with inb/outb
  */
-#define VIDC_BASE		0x80100000
-#define IOCEC4IO_BASE		0x8009c000
+#define IO_VIDC_BASE		0x80100000
 #ifdef CONFIG_ARCH_ARC
 #define LATCHAADDR		0x80094010
 #define LATCHBADDR		0x80094006
 #endif
-#define IOCECIO_BASE		0x80090000
 #define IOC_BASE		0x80080000
-#define MEMCECIO_BASE		0x80000000
+
+#define IO_EC_IOC4_BASE		0x8009c000
+#define IO_EC_IOC_BASE		0x80090000
+#define IO_EC_MEMC_BASE		0x80000000
 
 /*
  * IO definitions
@@ -57,23 +73,6 @@
 #define PCIO_BASE		0x03010000
 
 /*
- * Mapping areas
- */
-#define IO_END			0x03ffffff
-#define IO_BASE			0x03000000
-#define IO_SIZE			(IO_END - IO_BASE)
-#define IO_START		0x03000000
-
-/*
- * Screen mapping information
- */
-#define SCREEN2_END		0x02078000
-#define SCREEN2_BASE		0x02000000
-#define SCREEN1_END		SCREEN2_BASE
-#define SCREEN1_BASE		0x01f88000
-#define SCREEN_START		0x02000000
-
-/*
  * RAM definitions
  */
 #define MAPTOPHYS(a)		(((unsigned long)a & 0x007fffff) + PAGE_OFFSET)
@@ -88,7 +87,6 @@
 #define IOC_BASE		0x03200000
 #define PCIO_FLOPPYDMABASE	0x0302a000
 #define PCIO_BASE		0x03010000
-#define IO_BASE			0x03000000
 
 #endif
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-arc/ide.h linux/include/asm-arm/arch-arc/ide.h
--- v2.1.131/linux/include/asm-arm/arch-arc/ide.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-arc/ide.h	Thu Dec 17 09:05:42 1998
@@ -8,50 +8,44 @@
  *
  * Modifications:
  *  04-04-1998	PJB	Merged `arc' and `a5k' versions
+ *  01-07-1998	RMK	Added new ide_ioregspec_t
+ *  29-07-1998	RMK	Major re-work of IDE architecture specific code
  */
 
 #include <linux/config.h>
 #include <asm/irq.h>
 
-static __inline__ int
-ide_default_irq(ide_ioreg_t base)
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
 {
-#ifdef CONFIG_ARCH_A5K
-	if (base == 0x1f0)
-		return IRQ_HARDDISK;
-#endif
-	return 0;
-}
+	ide_ioreg_t reg = (ide_ioreg_t) data_port;
+	int i;
 
-static __inline__ ide_ioreg_t
-ide_default_io_base(int index)
-{
-#ifdef CONFIG_ARCH_A5K
-	if (index == 0)
-		return 0x1f0;
-#endif
-	return 0;
-}
+	memset(hw, 0, sizeof(*hw));
 
-static __inline__ int
-ide_default_stepping(int index)
-{
-	return 0;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+	hw->irq = irq;
 }
 
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
 static __inline__ void
-ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq)
+ide_init_default_hwifs(void)
 {
-	ide_ioreg_t port = base;
-	ide_ioreg_t ctrl = base + 0x206;
-	int i;
+#ifdef CONFIG_ARCH_A5K
+	hw_regs_t hw;
 
-	i = 8;
-	while (i--) {
-		*p++ = port;
-		port += 1 << stepping;
-	}
-	*p++ = ctrl;
-	if (irq != NULL)
-		*irq = 0;
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+	ide_register_hw(&hw, NULL);
+#endif
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-arc/keyboard.h linux/include/asm-arm/arch-arc/keyboard.h
--- v2.1.131/linux/include/asm-arm/arch-arc/keyboard.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-arc/keyboard.h	Thu Dec 17 09:05:42 1998
@@ -35,3 +35,5 @@
 #define kbd_sysrq_xlate			a5kkbd_sysrq_xlate
 #define kbd_disable_irq()		disable_irq(IRQ_KEYBOARDRX)
 #define kbd_enable_irq()		enable_irq(IRQ_KEYBOARDRX)
+
+#define SYSRQ_KEY	13
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-arc/processor.h linux/include/asm-arm/arch-arc/processor.h
--- v2.1.131/linux/include/asm-arm/arch-arc/processor.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-arc/processor.h	Thu Dec 17 09:05:42 1998
@@ -26,11 +26,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#if 0
-#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
-#else
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa110/hardware.h linux/include/asm-arm/arch-ebsa110/hardware.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa110/hardware.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa110/hardware.h	Thu Dec 17 09:05:42 1998
@@ -28,9 +28,8 @@
 /*
  * Mapping areas
  */
-#define IO_END			0xffffffff
 #define IO_BASE			0xe0000000
-#define IO_SIZE			(IO_END - IO_BASE)
+#define IO_SIZE			0x20000000
 #define IO_START		0xe0000000
 
 /*
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa110/processor.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-ebsa110/processor.h	Thu Dec 17 09:05:42 1998
@@ -23,11 +23,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#if 0
-#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
-#else
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/hardware.h linux/include/asm-arm/arch-ebsa285/hardware.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/hardware.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-ebsa285/hardware.h	Thu Dec 17 09:05:42 1998
@@ -20,11 +20,9 @@
  * 
  */
  
-#define IO_END			0xffffffff
 #define IO_BASE			0xe0000000
-#define IO_SIZE			(IO_END - IO_BASE)
-
-#define HAS_PCIO
+#define PCIO_BASE		0xffe00000
+ 
 
 #define XBUS_LEDS		((volatile unsigned char *)0xfff12000)
 #define XBUS_LED_AMBER		(1 << 0)
@@ -38,8 +36,6 @@
 #define XBUS_SWITCH_J17_11	((*XBUS_SWITCH) & (1 << 5))
 #define XBUS_SWITCH_J17_9	((*XBUS_SWITCH) & (1 << 6))
 
-#define PCIO_BASE		0xffe00000
- 
 #define CSR_SA110_CNTL		((volatile unsigned long *)0xfe00013c)
 #define CSR_PCIADDR_EXTN	((volatile unsigned long *)0xfe000140)
 #define CSR_PREFETCHMEMRANGE	((volatile unsigned long *)0xfe000144)
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/ide.h linux/include/asm-arm/arch-ebsa285/ide.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/ide.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/ide.h	Thu Dec 17 09:05:43 1998
@@ -1 +1,38 @@
-/* no ide */
+/*
+ * linux/include/asm-arm/arch-ebsa285/ide.h
+ *
+ * Copyright (c) 1998 Russell King
+ *
+ * Modifications:
+ *  29-07-1998	RMK	Major re-work of IDE architecture specific code
+ */
+#include <asm/irq.h>
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+{
+	ide_ioreg_t reg = (ide_ioreg_t) data_port;
+	int i;
+
+	memset(hw, 0, sizeof(*hw));
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+	hw->irq = irq;
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void
+ide_init_default_hwifs(void)
+{
+}
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/irq.h linux/include/asm-arm/arch-ebsa285/irq.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/irq.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-ebsa285/irq.h	Thu Dec 17 09:05:43 1998
@@ -5,8 +5,11 @@
  *
  * Changelog:
  *   22-08-1998	RMK	Restructured IRQ routines
+ *   03-09-1998	PJB	Merged CATS support
  */
 
+#include <linux/config.h>
+
 static void ebsa285_mask_irq(unsigned int irq)
 {
 	*CSR_IRQ_DISABLE = 1 << irq;
@@ -16,7 +19,73 @@
 {
 	*CSR_IRQ_ENABLE = 1 << irq;
 }
+
+#ifdef CONFIG_CATS
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int isa_irq_mask = 0xffff;
+
+#define cached_21	(isa_irq_mask & 0xff)
+#define cached_A1	((isa_irq_mask >> 8) & 0xff)
+
+#define update_8259(_irq)			\
+	if ((_irq) & 8)				\
+		outb(cached_A1, 0xa1);		\
+	else					\
+		outb(cached_21, 0x21);
+
+static void isa_interrupt(int irq, void *h, struct pt_regs *regs)
+{
+	asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
+	unsigned int irqbits = inb(0x20) | (inb(0xa0) << 8), irqnr = 0;
+	irqbits &= ~(1<<2);	/* don't try to service the cascade */
+	while (irqbits) {
+		if (irqbits & 1)
+			do_IRQ(32 + irqnr, regs);
+		irqbits >>= 1;
+		irqnr++;
+	}
+}
+
+static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+
+static struct irqaction irq_isa = 
+		{ isa_interrupt, SA_INTERRUPT, 0, "ISA PIC", NULL, NULL };
+static struct irqaction irq_cascade = 
+		{ no_action, 0, 0, "cascade", NULL, NULL };
+
+static void cats_mask_and_ack_isa_irq(unsigned int irq)
+{
+	isa_irq_mask |= (1 << (irq - 32));
+	update_8259(irq);
+	if (irq & 8) {
+		inb(0xA1);	/* DUMMY */
+		outb(cached_A1,0xA1);
+		outb(0x62,0x20);	/* Specific EOI to cascade */
+		outb(0x20,0xA0);
+	} else {
+		inb(0x21);	/* DUMMY */
+		outb(cached_21,0x21);
+		outb(0x20,0x20);
+	}
+}
+
+static void cats_mask_isa_irq(unsigned int irq)
+{
+	isa_irq_mask |= (1 << (irq - 32));
+	update_8259(irq);
+}
+
+static void cats_unmask_isa_irq(unsigned int irq)
+{
+	isa_irq_mask &= ~(1 << (irq - 32));
+	update_8259(irq);
+}
  
+#endif 
+
 static __inline__ void irq_init_irq(void)
 {
 	int irq;
@@ -27,8 +96,45 @@
 	for (irq = 0; irq < NR_IRQS; irq++) {
 		irq_desc[irq].valid	= 1;
 		irq_desc[irq].probe_ok	= 1;
-		irq_desc[irq].mask_ack	= ebsa285_mask_irq;
-		irq_desc[irq].mask	= ebsa285_mask_irq;
-		irq_desc[irq].unmask	= ebsa285_unmask_irq;
+#ifdef CONFIG_CATS
+		if (machine_is_cats() && IRQ_IS_ISA(irq)) {
+			irq_desc[irq].mask_ack	= cats_mask_and_ack_isa_irq;
+			irq_desc[irq].mask	= cats_mask_isa_irq;
+			irq_desc[irq].unmask	= cats_unmask_isa_irq;
+		} else
+#endif
+		{
+			irq_desc[irq].mask_ack	= ebsa285_mask_irq;
+			irq_desc[irq].mask	= ebsa285_mask_irq;
+			irq_desc[irq].unmask	= ebsa285_unmask_irq;
+		}
+	}
+
+#ifdef CONFIG_CATS
+	if (machine_is_cats()) {
+		request_region(0x20, 2, "pic1");
+		request_region(0xa0, 2, "pic2");
+
+		/* set up master 8259 */
+		outb(0x11, 0x20);
+		outb(0, 0x21);
+		outb(1<<2, 0x21);
+		outb(0x1, 0x21);
+		outb(0xff, 0x21);
+		outb(0x68, 0x20);
+		outb(0xa, 0x20);
+		
+		/* set up slave 8259 */
+		outb(0x11, 0xa0);
+		outb(0, 0xa1);
+		outb(2, 0xa1);
+		outb(0x1, 0xa1);
+		outb(0xff, 0xa1);
+		outb(0x68, 0xa0);
+		outb(0xa, 0xa0);
+
+		setup_arm_irq(IRQ_ISA_PIC, &irq_isa);
+		setup_arm_irq(IRQ_ISA_CASCADE, &irq_cascade);
 	}
+#endif
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/irqs.h linux/include/asm-arm/arch-ebsa285/irqs.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/irqs.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-ebsa285/irqs.h	Thu Dec 17 09:05:43 1998
@@ -2,9 +2,10 @@
  * linux/include/asm-arm/arch-ebsa285/irqs.h
  *
  * Copyright (C) 1998 Russell King
+ * Copyright (C) 1998 Phil Blundell
  */
 
-#define NR_IRQS			32
+#define NR_IRQS			48
 
 /*
  * This is a list of all interrupts that the 21285
@@ -39,10 +40,18 @@
 #define IRQ_PCITARGETABORT	30
 #define IRQ_PCIPARITY		31
 
+/* IRQs 32-47 are the 16 ISA interrupts on a CATS board.  */
+#define IRQ_ISA_PIC	IRQ_IN2
+#define IRQ_IS_ISA(_x)	(((_x) >= 32) && ((_x) <= 47))
+#define IRQ_ISA(_x)	((_x) + 0x20)
+#define IRQ_ISA_CASCADE		IRQ_ISA(2)
+
 /*
  * Now map them to the Linux interrupts
  */
 #define IRQ_TIMER		IRQ_TIMER1
+#define IRQ_FLOPPYDISK		IRQ_ISA(6)
+#define IRQ_HARDDISK		IRQ_ISA(14)
+#define IRQ_HARDDISK_SECONDARY	IRQ_ISA(15)
 
-#define irq_cannonicalize(i)	(i)
-
+#define irq_cannonicalize(_i)	(((_i) == IRQ_ISA_CASCADE) ? IRQ_ISA(9) : _i)
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/keyboard.h linux/include/asm-arm/arch-ebsa285/keyboard.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/keyboard.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/keyboard.h	Thu Dec 17 09:05:43 1998
@@ -4,16 +4,48 @@
  * Keyboard driver definitions for EBSA285 architecture
  *
  * (C) 1998 Russell King
+ * (C) 1998 Phil Blundell
  */
 
 #include <linux/config.h>
 #include <asm/irq.h>
+#include <asm/system.h>
 
 #define NR_SCANCODES 128
 
-#ifdef CONFIG_MAGIC_SYSRQ
-static unsigned char kbd_sysrq_xlate[NR_SCANCODES];
-#endif
+#ifdef CONFIG_CATS
+
+#define KEYBOARD_IRQ		IRQ_ISA(1)
+
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+
+#define kbd_setkeycode			pckbd_setkeycode
+#define kbd_getkeycode			pckbd_getkeycode
+#define kbd_pretranslate		pckbd_pretranslate
+#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \
+		pckbd_translate(sc & 0x7f, kcp, rm);})
+
+#define kbd_unexpected_up		pckbd_unexpected_up
+#define kbd_leds			pckbd_leds
+#define kbd_init_hw()			\
+		do { if (machine_is_cats()) pckbd_init_hw(); } while (0)
+#define kbd_sysrq_xlate			pckbd_sysrq_xlate
+#define kbd_disable_irq()
+#define kbd_enable_irq()
+
+#define SYSRQ_KEY	0x54
+
+#else
+
+/* Dummy keyboard definitions */
 
 #define kbd_setkeycode(sc,kc)		(-EINVAL)
 #define kbd_getkeycode(sc)		(-EINVAL)
@@ -35,3 +67,6 @@
 #define kbd_disable_irq()
 #define kbd_enable_irq()
 
+#define SYSRQ_KEY	13
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/mmu.h linux/include/asm-arm/arch-ebsa285/mmu.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/mmu.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-ebsa285/mmu.h	Thu Dec 17 09:05:43 1998
@@ -7,6 +7,7 @@
  *  20-10-1996	RMK	Created
  *  31-12-1997	RMK	Fixed definitions to reduce warnings
  *  17-05-1998	DAG	Added __virt_to_bus and __bus_to_virt functions.
+ *  21-11-1998	RMK	Changed __virt_to_bus and __bus_to_virt to macros.
  */
 #ifndef __ASM_ARCH_MMU_H
 #define __ASM_ARCH_MMU_H
@@ -19,7 +20,9 @@
 #define __phys_to_virt__is_a_macro
 #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
 
-extern unsigned long __virt_to_bus(unsigned long);
-extern unsigned long __bus_to_virt(unsigned long);
+#define __virt_to_bus__is_a_macro
+#define __virt_to_bus(x)	(x - 0xe0000000)
+#define __bus_to_virt__is_a_macro
+#define __bus_to_virt(x)	(x + 0xe0000000)
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/processor.h linux/include/asm-arm/arch-ebsa285/processor.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/processor.h	Tue Jun 23 10:01:25 1998
+++ linux/include/asm-arm/arch-ebsa285/processor.h	Thu Dec 17 09:05:43 1998
@@ -23,11 +23,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#if 0
-#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
-#else
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/serial.h linux/include/asm-arm/arch-ebsa285/serial.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/serial.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-ebsa285/serial.h	Thu Dec 17 09:05:43 1998
@@ -5,10 +5,14 @@
  *
  * Changelog:
  *  15-10-1996	RMK	Created
+ *  25-05-1998	PJB	CATS support
  */
 #ifndef __ASM_ARCH_SERIAL_H
 #define __ASM_ARCH_SERIAL_H
 
+#include <linux/config.h>
+#include <asm/irq.h>
+
 /*
  * This assumes you have a 1.8432 MHz clock for your UART.
  *
@@ -18,23 +22,31 @@
  */
 #define BASE_BAUD (1843200 / 16)
 
+#ifdef CONFIG_CATS
+#define _SER_IRQ0	IRQ_ISA(4)
+#define _SER_IRQ1	IRQ_ISA(3)
+#else
+#define _SER_IRQ0	0
+#define _SER_IRQ1	0
+#endif
+
 #define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
 
      /* UART CLK        PORT  IRQ     FLAGS        */
 #define SERIAL_PORT_DFNS \
-	{ 0, BASE_BAUD, 0x3F8,  0, STD_COM_FLAGS },	/* ttyS0 */	\
-	{ 0, BASE_BAUD, 0x2F8,  0, STD_COM_FLAGS },	/* ttyS1 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS2 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS3 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS }, 	/* ttyS4 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS5 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS6 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS7 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS8 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS9 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS10 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS11 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS12 */	\
-	{ 0, BASE_BAUD, 0    ,  0, STD_COM_FLAGS },	/* ttyS13 */
+	{ 0, BASE_BAUD, 0x3F8, _SER_IRQ0, STD_COM_FLAGS },	/* ttyS0 */	\
+	{ 0, BASE_BAUD, 0x2F8, _SER_IRQ1, STD_COM_FLAGS },	/* ttyS1 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS2 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS3 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS }, 	/* ttyS4 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS5 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS6 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS7 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS8 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS9 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS10 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS11 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS12 */	\
+	{ 0, BASE_BAUD, 0    , 0        , STD_COM_FLAGS },	/* ttyS13 */
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-ebsa285/time.h linux/include/asm-arm/arch-ebsa285/time.h
--- v2.1.131/linux/include/asm-arm/arch-ebsa285/time.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/arch-ebsa285/time.h	Thu Dec 17 09:05:43 1998
@@ -2,14 +2,21 @@
  * linux/include/asm-arm/arch-ebsa285/time.h
  *
  * Copyright (c) 1998 Russell King.
+ * Copyright (c) 1998 Phil Blundell
  *
- * No real time clock on the evalulation board!
+ * CATS has a real-time clock, though the evaluation board doesn't.
  *
  * Changelog:
  *  21-Mar-1998	RMK	Created
+ *  27-Aug-1998	PJB	CATS support
  */
 
+#define RTC_PORT(x)		(0x72+(x))
+#define RTC_ALWAYS_BCD		1
+
 #include <asm/leds.h>
+#include <asm/system.h>
+#include <linux/mc146818rtc.h>
 
 extern __inline__ unsigned long gettimeoffset (void)
 {
@@ -18,22 +25,27 @@
 
 extern __inline__ int reset_timer (void)
 {
-	static unsigned int count = 50;
-	static int last_pid;
-
 	*CSR_TIMER1_CLR = 0;
 
-	if (current->pid != last_pid) {
-		last_pid = current->pid;
-		if (last_pid)
-			leds_event(led_idle_end);
-		else
-			leds_event(led_idle_start);
-	}
-
-	if (--count == 0) {
-		count = 50;
-		leds_event(led_timer);
+	/*
+	 * Do the LEDs thing on EBSA-285 hardware.
+	 */
+	if (!machine_is_cats()) {
+		static unsigned int count = 50;
+		static int last_pid;
+
+		if (current->pid != last_pid) {
+			last_pid = current->pid;
+			if (last_pid)
+				leds_event(led_idle_end);
+			else
+				leds_event(led_idle_start);
+		}
+		
+		if (--count == 0) {
+			count = 50;
+			leds_event(led_timer);
+		}
 	}
 
 	return 1;
@@ -49,9 +61,59 @@
  */
 extern __inline__ unsigned long setup_timer (void)
 {
+	int year, mon, day, hour, min, sec;
+
+	/*
+	 * Default the date to 1 Jan 1970 0:0:0
+	 */
+	year = 1970; mon = 1; day = 1;
+	hour = 0; min = 0; sec = 0;
+
 	*CSR_TIMER1_CLR  = 0;
 	*CSR_TIMER1_LOAD = LATCH;
 	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
 
-	return mktime(1970, 1, 1, 0, 0, 0);
+	if (machine_is_cats()) 
+	{
+		int i;
+		/*
+		 * Read the real time from the Dallas chip.  (Code borrowed
+		 * from arch/i386/kernel/time.c).
+		 */
+		
+		/* The Linux interpretation of the CMOS clock register contents:
+		 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+		 * RTC registers show the second which has precisely just started.
+		 * Let's hope other operating systems interpret the RTC the same way.
+		 */
+
+		/* read RTC exactly on falling edge of update flag */
+		for (i = 0 ; i < 1000000 ; i++)	/* may take up to 1 second... */
+			if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+				break;
+		for (i = 0 ; i < 1000000 ; i++)	/* must try at least 2.228 ms */
+			if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+				break;
+		do { /* Isn't this overkill ? UIP above should guarantee consistency */
+			sec = CMOS_READ(RTC_SECONDS);
+			min = CMOS_READ(RTC_MINUTES);
+			hour = CMOS_READ(RTC_HOURS);
+			day = CMOS_READ(RTC_DAY_OF_MONTH);
+			mon = CMOS_READ(RTC_MONTH);
+			year = CMOS_READ(RTC_YEAR);
+		} while (sec != CMOS_READ(RTC_SECONDS));
+		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		{
+			BCD_TO_BIN(sec);
+			BCD_TO_BIN(min);
+			BCD_TO_BIN(hour);
+			BCD_TO_BIN(day);
+			BCD_TO_BIN(mon);
+			BCD_TO_BIN(year);
+		}
+		if ((year += 1900) < 1970)
+			year += 100;
+	}
+
+	return mktime(year, mon, day, hour, min, sec);
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-nexuspci/hardware.h linux/include/asm-arm/arch-nexuspci/hardware.h
--- v2.1.131/linux/include/asm-arm/arch-nexuspci/hardware.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-nexuspci/hardware.h	Thu Dec 17 09:05:43 1998
@@ -27,9 +27,7 @@
 /*
  * Mapping areas
  */
-#define IO_END			0xffffffff
 #define IO_BASE			0xfe000000
-#define IO_SIZE			(IO_END - IO_BASE)
 
 /*
  * RAM definitions
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-nexuspci/processor.h linux/include/asm-arm/arch-nexuspci/processor.h
--- v2.1.131/linux/include/asm-arm/arch-nexuspci/processor.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-nexuspci/processor.h	Thu Dec 17 09:05:43 1998
@@ -24,11 +24,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#if 0
-#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
-#else
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-rpc/hardware.h linux/include/asm-arm/arch-rpc/hardware.h
--- v2.1.131/linux/include/asm-arm/arch-rpc/hardware.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-rpc/hardware.h	Thu Dec 17 09:05:43 1998
@@ -13,33 +13,45 @@
  * What hardware must be present
  */
 #define HAS_IOMD
-#define HAS_PCIO
 #define HAS_VIDC20
 
-/*
- * Optional hardware
- */
-#define HAS_EXPMASK
-
-/*
- * Physical definitions
+/* Hardware addresses of major areas.
+ *  *_START is the physical address
+ *  *_SIZE  is the size of the region
+ *  *_BASE  is the virtual address
  */
+#define RAM_SIZE		0x10000000
 #define RAM_START		0x10000000
-#define IO_START		0x03000000
+
+#define EASI_SIZE		0x08000000	/* EASI I/O */
+#define EASI_START		0x08000000
+#define EASI_BASE		0xe8000000
+
+#define IO_START		0x03000000	/* I/O */
+#define IO_SIZE			0x01000000
+#define IO_BASE			0xe0000000
+
 #define SCREEN_START		0x02000000	/* VRAM */
+#define SCREEN2_END		0xe0000000
+#define SCREEN2_BASE		0xd8000000
+#define SCREEN1_END		0xd8000000
+#define SCREEN1_BASE		0xd0000000
+
 
 #ifndef __ASSEMBLER__
 
 /*
  * for use with inb/outb
  */
-#define VIDC_AUDIO_BASE		0x80140000
-#define VIDC_BASE		0x80100000
-#define IOCEC4IO_BASE		0x8009c000
-#define IOCECIO_BASE		0x80090000
-#define IOMD_BASE		0x80080000
-#define MEMCEC8IO_BASE		0x8000ac00
-#define MEMCECIO_BASE		0x80000000
+#define IO_VIDC_AUDIO_BASE	0x80140000
+#define IO_VIDC_BASE		0x80100000
+#define IO_IOMD_BASE		0x80080000
+
+#define IO_EC_EASI_BASE		0x82000000
+#define IO_EC_IOC4_BASE		0x8009c000
+#define IO_EC_IOC_BASE		0x80090000
+#define IO_EC_MEMC8_BASE	0x8000ac00
+#define IO_EC_MEMC_BASE		0x80000000
 
 /*
  * IO definitions
@@ -51,21 +63,6 @@
 #define PCIO_BASE		0xe0010000
 
 /*
- * Mapping areas
- */
-#define IO_END			0xe1000000
-#define IO_BASE			0xe0000000
-#define IO_SIZE			(IO_END - IO_BASE)
-
-/*
- * Screen mapping information
- */
-#define SCREEN2_END		0xe0000000
-#define SCREEN2_BASE		0xd8000000
-#define SCREEN1_END		SCREEN2_BASE
-#define SCREEN1_BASE		0xd0000000
-
-/*
  * Offsets from RAM base
  */
 #define PARAMS_OFFSET		0x0100
@@ -95,7 +92,6 @@
 #define IOC_BASE		0xe0200000
 #define PCIO_FLOPPYDMABASE	0xe002a000
 #define PCIO_BASE		0xe0010000
-#define IO_BASE			0xe0000000
 
 #endif
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-rpc/ide.h linux/include/asm-arm/arch-rpc/ide.h
--- v2.1.131/linux/include/asm-arm/arch-rpc/ide.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/arch-rpc/ide.h	Thu Dec 17 09:05:43 1998
@@ -2,44 +2,41 @@
  * linux/include/asm-arm/arch-rpc/ide.h
  *
  * Copyright (c) 1997 Russell King
+ *
+ * Modifications:
+ *  29-07-1998	RMK	Major re-work of IDE architecture specific code
  */
 #include <asm/irq.h>
 
-static __inline__ int
-ide_default_irq(ide_ioreg_t base)
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
 {
-	if (base == 0x1f0)
-		return IRQ_HARDDISK;
-	return 0;
-}
+	ide_ioreg_t reg = (ide_ioreg_t) data_port;
+	int i;
 
-static __inline__ ide_ioreg_t
-ide_default_io_base(int index)
-{
-	if (index == 0)
-		return 0x1f0;
-	return 0;
-}
+	memset(hw, 0, sizeof(*hw));
 
-static __inline__ int
-ide_default_stepping(int index)
-{
-	return 0;
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+	hw->irq = irq;
 }
 
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
 static __inline__ void
-ide_init_hwif_ports (ide_ioreg_t *p, ide_ioreg_t base, int stepping, int *irq)
+ide_init_default_hwifs(void)
 {
-	ide_ioreg_t port = base;
-	ide_ioreg_t ctrl = base + 0x206;
-	int i;
+	hw_regs_t hw;
 
-	i = 8;
-	while (i--) {
-		*p++ = port;
-		port += 1 << stepping;
-	}
-	*p++ = ctrl;
-	if (irq != NULL)
-		*irq = 0;
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+	ide_register_hw(&hw, NULL);
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-rpc/keyboard.h linux/include/asm-arm/arch-rpc/keyboard.h
--- v2.1.131/linux/include/asm-arm/arch-rpc/keyboard.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-rpc/keyboard.h	Thu Dec 17 09:05:43 1998
@@ -40,3 +40,4 @@
 #define kbd_disable_irq()		disable_irq(IRQ_KEYBOARDRX)
 #define kbd_enable_irq()		enable_irq(IRQ_KEYBOARDRX)
 
+#define SYSRQ_KEY	13
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-rpc/processor.h linux/include/asm-arm/arch-rpc/processor.h
--- v2.1.131/linux/include/asm-arm/arch-rpc/processor.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-rpc/processor.h	Thu Dec 17 09:05:43 1998
@@ -26,11 +26,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#if 0
-#define TASK_UNMAPPED_BASE(off)	(TASK_SIZE / 3)
-#else
 #define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-#endif
 #define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/hardware.h linux/include/asm-arm/arch-vnc/hardware.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/hardware.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/hardware.h	Thu Dec 17 09:05:43 1998
@@ -7,84 +7,20 @@
  */
 
 /*    Logical    Physical
- * 0xfff00000	0x40000000	X-Bus
  * 0xffe00000	0x7c000000	PCI I/O space
- *
  * 0xfe000000	0x42000000	CSR
  * 0xfd000000	0x78000000	Outbound write flush
  * 0xfc000000	0x79000000	PCI IACK/special space
- *
- * 0xf9030000	0x7a080000	PCI Config type 1 card 4
- * 0xf9020000	0x7a040000	PCI Config type 1 card 3
- * 0xf9010000	0x7a020000	PCI Config type 1 card 2
- * 0xf9000000	0x7a010000	PCI Config type 1 card 1
- *
- * 0xf8030000	0x7b080000	PCI Config type 0 card 4
- * 0xf8020000	0x7b040000	PCI Config type 0 card 3
- * 0xf8010000	0x7b020000	PCI Config type 0 card 2
- * 0xf8000000	0x7b010000	PCI Config type 0 card 1
+ * 0xf9000000	0x7a000000	PCI Config type 1
+ * 0xf8000000	0x7b000000	PCI Config type 0
  * 
  */
- 
-/*
- * DEC21285
- */
-#define CSR_SA110_CNTL		((volatile unsigned long *)0xfe00013c)
-#define CSR_PCIADDR_EXTN	((volatile unsigned long *)0xfe000140)
-#define CSR_PREFETCHMEMRANGE	((volatile unsigned long *)0xfe000144)
-#define CSR_XBUS_CYCLE		((volatile unsigned long *)0xfe000148)
-#define CSR_XBUS_IOSTROBE	((volatile unsigned long *)0xfe00014c)
-#define CSR_DOORBELL_PCI	((volatile unsigned long *)0xfe000150)
-#define CSR_DOORBELL_SA110	((volatile unsigned long *)0xfe000154)
-
-
-#define CSR_UARTDR		((volatile unsigned long *)0xfe000160)
-#define CSR_RXSTAT		((volatile unsigned long *)0xfe000164)
-#define CSR_H_UBRLCR		((volatile unsigned long *)0xfe000168)
-#define CSR_M_UBRLCR		((volatile unsigned long *)0xfe00016c)
-#define CSR_L_UBRLCR		((volatile unsigned long *)0xfe000170)
-#define CSR_UARTCON		((volatile unsigned long *)0xfe000174)
-#define CSR_UARTFLG		((volatile unsigned long *)0xfe000178)
-
-#define CSR_IRQ_STATUS		((volatile unsigned long *)0xfe000180)
-#define CSR_IRQ_RAWSTATUS	((volatile unsigned long *)0xfe000184)
-#define CSR_IRQ_ENABLE		((volatile unsigned long *)0xfe000188)
-#define CSR_IRQ_DISABLE		((volatile unsigned long *)0xfe00018c)
-#define CSR_IRQ_SOFT		((volatile unsigned long *)0xfe000190)
-
-#define CSR_FIQ_STATUS		((volatile unsigned long *)0xfe000280)
-#define CSR_FIQ_RAWSTATUS	((volatile unsigned long *)0xfe000284)
-#define CSR_FIQ_ENABLE		((volatile unsigned long *)0xfe000288)
-#define CSR_FIQ_DISABLE		((volatile unsigned long *)0xfe00028c)
-#define CSR_FIQ_SOFT		((volatile unsigned long *)0xfe000290)
-
-#define CSR_TIMER1_LOAD		((volatile unsigned long *)0xfe000300)
-#define CSR_TIMER1_VALUE	((volatile unsigned long *)0xfe000304)
-#define CSR_TIMER1_CNTL		((volatile unsigned long *)0xfe000308)
-#define CSR_TIMER1_CLR		((volatile unsigned long *)0xfe00030c)
-
-#define CSR_TIMER2_LOAD		((volatile unsigned long *)0xfe000320)
-#define CSR_TIMER2_VALUE	((volatile unsigned long *)0xfe000324)
-#define CSR_TIMER2_CNTL		((volatile unsigned long *)0xfe000328)
-#define CSR_TIMER2_CLR		((volatile unsigned long *)0xfe00032c)
-
-#define CSR_TIMER3_LOAD		((volatile unsigned long *)0xfe000340)
-#define CSR_TIMER3_VALUE	((volatile unsigned long *)0xfe000344)
-#define CSR_TIMER3_CNTL		((volatile unsigned long *)0xfe000348)
-#define CSR_TIMER3_CLR		((volatile unsigned long *)0xfe00034c)
-
-#define CSR_TIMER4_LOAD		((volatile unsigned long *)0xfe000360)
-#define CSR_TIMER4_VALUE	((volatile unsigned long *)0xfe000364)
-#define CSR_TIMER4_CNTL		((volatile unsigned long *)0xfe000368)
-#define CSR_TIMER4_CLR		((volatile unsigned long *)0xfe00036c)
-
-#define TIMER_CNTL_ENABLE	(1 << 7)
-#define TIMER_CNTL_AUTORELOAD	(1 << 6)
-#define TIMER_CNTL_DIV1		(0)
-#define TIMER_CNTL_DIV16	(1 << 2)
-#define TIMER_CNTL_DIV256	(2 << 2)
-#define TIMER_CNTL_CNTEXT	(3 << 2)
 
+#include <asm/dec21285.h>
+
+#define IO_BASE_ARM_CSR		0xfe000000
+#define PCI_IACK		0xfc000000
+ 
 /* LEDs */
 #define XBUS_LEDS		((volatile unsigned char *)0xfff12000)
 #define XBUS_LED_AMBER		(1 << 0)
@@ -103,18 +39,11 @@
 #define IO_SIZE			(IO_END - IO_BASE)
 
 #define HAS_PCIO
-
-#define XBUS_SWITCH		((volatile unsigned char *)0xfff12000)
-#define XBUS_SWITCH_SWITCH	((*XBUS_SWITCH) & 15)
-#define XBUS_SWITCH_J17_13	((*XBUS_SWITCH) & (1 << 4))
-#define XBUS_SWITCH_J17_11	((*XBUS_SWITCH) & (1 << 5))
-#define XBUS_SWITCH_J17_9	((*XBUS_SWITCH) & (1 << 6))
-
 #define PCIO_BASE		0xffe00000
 
 #define KERNTOPHYS(a)		((unsigned long)(&a))
 
-#define PARAMS_OFFSET		0x0100
-#define PARAMS_BASE		(PAGE_OFFSET + PARAMS_OFFSET)
+//#define PARAMS_OFFSET		0x0100
+//#define PARAMS_BASE		(PAGE_OFFSET + PARAMS_OFFSET)
 
 #define SAFE_ADDR		0x50000000
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/ide.h linux/include/asm-arm/arch-vnc/ide.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/ide.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/ide.h	Thu Dec 17 09:05:43 1998
@@ -1 +1,42 @@
-/* no ide */
+/*
+ * linux/include/asm-arm/arch-vnc/ide.h
+ *
+ * Copyright (c) 1998 Russell King
+ *
+ * Modifications:
+ *  29-07-1998	RMK	Major re-work of IDE architecture specific code
+ */
+#include <asm/irq.h>
+
+/*
+ * Set up a hw structure for a specified data port, control port and IRQ.
+ * This should follow whatever the default interface uses.
+ */
+static __inline__ void
+ide_init_hwif_ports(hw_regs_t *hw, int data_port, int ctrl_port, int irq)
+{
+	ide_ioreg_t reg = (ide_ioreg_t) data_port;
+	int i;
+
+	memset(hw, 0, sizeof(*hw));
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = reg;
+		reg += 1;
+	}
+	hw->io_ports[IDE_CONTROL_OFFSET] = (ide_ioreg_t) ctrl_port;
+	hw->irq = irq;
+}
+
+/*
+ * This registers the standard ports for this architecture with the IDE
+ * driver.
+ */
+static __inline__ void
+ide_init_default_hwifs(void)
+{
+	hw_regs_t hw;
+
+	ide_init_hwif_ports(&hw, 0x1f0, 0x3f6, IRQ_HARDDISK);
+	ide_register_hw(&hw, NULL);
+}
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/io.h linux/include/asm-arm/arch-vnc/io.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/io.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/io.h	Thu Dec 17 09:05:43 1998
@@ -163,12 +163,12 @@
 	return *(volatile unsigned short *)(0xe0000000 + (addr));
 }
 
-static inline void writew(unsigned long b, unsigned int addr)
+static inline void writel(unsigned long b, unsigned int addr)
 {
 	*(volatile unsigned long *)(0xe0000000 + (addr)) = b;
 }
 
-static inline unsigned long readw(unsigned int addr)
+static inline unsigned long readl(unsigned int addr)
 {
 	return *(volatile unsigned long *)(0xe0000000 + (addr));
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/irq.h linux/include/asm-arm/arch-vnc/irq.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/irq.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/irq.h	Thu Dec 17 09:05:43 1998
@@ -7,6 +7,7 @@
  *   22-08-1998	RMK	Restructured IRQ routines
  */
 
+#include <asm/dec21285.h>
 #include <asm/irq.h>
 
 /*
@@ -39,7 +40,7 @@
 
 static void vnc_unmask_csr_irq(unsigned int irq)
 {
-	*CSR_IRQ_DISABLE = fb_irq_mask[irq];
+	*CSR_IRQ_ENABLE = fb_irq_mask[irq];
 }
 
 static void vnc_mask_pic_lo_irq(unsigned int irq)
@@ -49,11 +50,19 @@
 	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
 }
 
-static void vnc_unmask_pic_lo_irq(unsigned int irq)
+static void vnc_mask_ack_pic_lo_irq(unsigned int irq)
 {
 	unsigned int mask = 1 << (irq & 7);
 
-	outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
+	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
+	outb(0x20, PIC_LO);
+}
+
+static void vnc_unmask_pic_lo_irq(unsigned int irq)
+{
+	unsigned int mask = ~(1 << (irq & 7));
+
+	outb(inb(PIC_MASK_LO) & mask, PIC_MASK_LO);
 }
 
 static void vnc_mask_pic_hi_irq(unsigned int irq)
@@ -63,6 +72,15 @@
 	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
 }
 
+static void vnc_mask_ack_pic_hi_irq(unsigned int irq)
+{
+	unsigned int mask = 1 << (irq & 7);
+
+	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
+	outb(0x62, PIC_LO);
+	outb(0x20, PIC_HI);
+}
+
 static void vnc_unmask_pic_hi_irq(unsigned int irq)
 {
 	unsigned int mask = 1 << (irq & 7);
@@ -70,6 +88,12 @@
 	outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
 }
 
+static void no_action(int irq, void *dev_id, struct pt_regs *regs)
+{
+}
+
+static struct irqaction irq_cascade = { no_action, 0, 0, "cascade", NULL, NULL };
+
 static __inline__ void irq_init_irq(void)
 {
 	unsigned int irq;
@@ -97,13 +121,36 @@
 			irq_desc[irq].mask	= vnc_mask_csr_irq;
 			irq_desc[irq].unmask	= vnc_unmask_csr_irq;
 		} else if (irq < 24) {
-			irq_desc[irq].mask_ack	= vnc_mask_pic_lo_irq;
+irq_desc[irq].probe_ok = 0;
+			irq_desc[irq].mask_ack	= vnc_mask_ack_pic_lo_irq;
 			irq_desc[irq].mask	= vnc_mask_pic_lo_irq;
 			irq_desc[irq].unmask	= vnc_unmask_pic_lo_irq;
 		} else {
-			irq_desc[irq].mask_ack	= vnc_mask_pic_hi_irq;
+irq_desc[irq].probe_ok = 0;
+			irq_desc[irq].mask_ack	= vnc_mask_ack_pic_hi_irq;
 			irq_desc[irq].mask	= vnc_mask_pic_hi_irq;
 			irq_desc[irq].unmask	= vnc_unmask_pic_hi_irq;
 		}
 	}
+
+	irq_desc[0].probe_ok = 0;
+	irq_desc[IRQ_SOFTIRQ].probe_ok = 0;
+	irq_desc[IRQ_CONRX].probe_ok = 0;
+	irq_desc[IRQ_CONTX].probe_ok = 0;
+	irq_desc[IRQ_TIMER0].probe_ok = 0;
+	irq_desc[IRQ_TIMER1].probe_ok = 0;
+	irq_desc[IRQ_TIMER2].probe_ok = 0;
+	irq_desc[IRQ_WATCHDOG].probe_ok = 0;
+	irq_desc[IRQ_DMA1].probe_ok = 0;
+	irq_desc[13].probe_ok = 0;
+	irq_desc[14].probe_ok = 0;
+	irq_desc[IRQ_PCI_ERR].probe_ok = 0;
+	irq_desc[IRQ_PIC_HI].probe_ok = 0;
+	irq_desc[29].probe_ok = 0;
+	irq_desc[31].probe_ok = 0;
+
+	outb(0xff, PIC_MASK_LO);
+	outb(0xff, PIC_MASK_HI);
+
+	setup_arm_irq(IRQ_PIC_HI, &irq_cascade);
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/irqs.h linux/include/asm-arm/arch-vnc/irqs.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/irqs.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/irqs.h	Thu Dec 17 09:05:43 1998
@@ -47,8 +47,8 @@
 #define IRQ_MASK_TIMER1		0x00000020
 #define IRQ_MASK_TIMER2		0x00000040
 #define IRQ_MASK_WATCHDOG	0x00000080
-#define IRQ_MASK_ETHERH10	0x00000100
-#define IRQ_MASK_ETHERH100	0x00000200
+#define IRQ_MASK_ETHER10	0x00000100
+#define IRQ_MASK_ETHER100	0x00000200
 #define IRQ_MASK_VIDCOMP	0x00000400
 #define IRQ_MASK_EXTERN_IRQ	0x00000800
 #define IRQ_MASK_DMA1		0x00030000
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/keyboard.h linux/include/asm-arm/arch-vnc/keyboard.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/keyboard.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/arch-vnc/keyboard.h	Thu Dec 17 09:05:43 1998
@@ -1,36 +1,38 @@
 /*
- * linux/include/asm-arm/arch-ebsa285/keyboard.h
+ * linux/include/asm-arm/arch-vnc/keyboard.h
  *
- * Keyboard driver definitions for EBSA285 architecture
+ * Keyboard driver definitions for VNC architecture
  *
  * (C) 1998 Russell King
  */
 
-#include <linux/config.h>
 #include <asm/irq.h>
 
 #define NR_SCANCODES 128
 
-#ifdef CONFIG_MAGIC_SYSRQ
-static unsigned char kbd_sysrq_xlate[NR_SCANCODES];
-#endif
+#define KEYBOARD_IRQ			IRQ_KEYBOARD
 
-#define kbd_setkeycode(sc,kc)		(-EINVAL)
-#define kbd_getkeycode(sc)		(-EINVAL)
-
-/* Prototype: int kbd_pretranslate(scancode, raw_mode)
- * Returns  : 0 to ignore scancode
- */
-#define kbd_pretranslate(sc,rm)		(1)
-
-/* Prototype: int kbd_translate(scancode, *keycode, *up_flag, raw_mode)
- * Returns  : 0 to ignore scancode, *keycode set to keycode, *up_flag
- *            set to 0200 if scancode indicates release
- */
-#define kbd_translate(sc, kcp, ufp, rm)	(1)
-#define kbd_unexpected_up(kc)		(0200)
-#define kbd_leds(leds)
-#define kbd_init_hw()
-//#define kbd_sysrq_xlate			ps2kbd_sysrq_xlate
+extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode);
+extern int pckbd_getkeycode(unsigned int scancode);
+extern int pckbd_pretranslate(unsigned char scancode, char raw_mode);
+extern int pckbd_translate(unsigned char scancode, unsigned char *keycode,
+			   char raw_mode);
+extern char pckbd_unexpected_up(unsigned char keycode);
+extern void pckbd_leds(unsigned char leds);
+extern void pckbd_init_hw(void);
+extern unsigned char pckbd_sysrq_xlate[128];
+
+#define kbd_setkeycode			pckbd_setkeycode
+#define kbd_getkeycode			pckbd_getkeycode
+#define kbd_pretranslate		pckbd_pretranslate
+#define kbd_translate(sc, kcp, ufp, rm) ({ *ufp = sc & 0200; \
+		pckbd_translate(sc & 0x7f, kcp, rm);})
+
+#define kbd_unexpected_up		pckbd_unexpected_up
+#define kbd_leds			pckbd_leds
+#define kbd_init_hw()			pckbd_init_hw()
+#define kbd_sysrq_xlate			pckbd_sysrq_xlate
 #define kbd_disable_irq()
 #define kbd_enable_irq()
+
+#define SYSRQ_KEY 0x54
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/mmu.h linux/include/asm-arm/arch-vnc/mmu.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/mmu.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/mmu.h	Thu Dec 17 09:05:43 1998
@@ -19,8 +19,8 @@
 #define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET)
 
 #define __virt_to_bus__is_a_macro
-#define __virt_to_bus(x)	(x)
+#define __virt_to_bus(x)	(x - 0xe0000000)
 #define __bus_to_virt__is_a_macro
-#define __bus_to_virt(x)	(x)
+#define __bus_to_virt(x)	(x + 0xe0000000)
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/processor.h linux/include/asm-arm/arch-vnc/processor.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/processor.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/processor.h	Thu Dec 17 09:05:43 1998
@@ -24,6 +24,7 @@
  * space during mmap's.
  */
 #define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_ALIGN(addr, off)	PAGE_ALIGN(addr)
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, NULL, &init_mm.mmap }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/system.h linux/include/asm-arm/arch-vnc/system.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/system.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/system.h	Thu Dec 17 09:05:43 1998
@@ -2,19 +2,36 @@
  * linux/include/asm-arm/arch-ebsa285/system.h
  *
  * Copyright (c) 1996,1997,1998 Russell King.
+ * Copyright (c) 1998 Corel Computer Corp.
  */
 #include <asm/hardware.h>
+#include <asm/dec21285.h>
 #include <asm/leds.h>
+#include <asm/io.h>
 
-/* To reboot, we set up the 21285 watchdog and enable it.
- * We then wait for it to timeout.
- */
 extern __inline__ void arch_hard_reset (void)
 {
 	cli();
-	*CSR_TIMER4_LOAD = 0x8000;
-	*CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
-	*CSR_SA110_CNTL |= 1 << 13;
+
+	/* open up the SuperIO chip
+	 */
+	outb(0x87, 0x370);
+	outb(0x87, 0x370);
+
+	/* aux function group 1 (Logical Device 7)
+	 */
+	outb(0x07, 0x370);
+	outb(0x07, 0x371);
+
+	/* set GP16 for WD-TIMER output
+	 */
+	outb(0xE6, 0x370);
+	outb(0x00, 0x371);
+
+	/* set a RED LED and toggle WD_TIMER for rebooting...
+	 */
+	outb(0xC4, 0x338);
+	
 	while(1);
 }
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/arch-vnc/time.h linux/include/asm-arm/arch-vnc/time.h
--- v2.1.131/linux/include/asm-arm/arch-vnc/time.h	Tue Jul 21 00:15:32 1998
+++ linux/include/asm-arm/arch-vnc/time.h	Thu Dec 17 09:05:43 1998
@@ -6,6 +6,11 @@
  *  -- Russell King.
  */
 
+#include <linux/mc146818rtc.h>
+
+#undef IRQ_TIMER
+#define IRQ_TIMER		IRQ_TIMER4
+
 extern __inline__ unsigned long gettimeoffset (void)
 {
 	return 0;
@@ -13,28 +18,157 @@
 
 extern __inline__ int reset_timer (void)
 {
-	*CSR_TIMER1_CLR = 0;
 	return 1;
 }
 
+unsigned long set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */
+	CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
+
+	save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */
+	CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
+		BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+			BIN_TO_BCD(real_seconds);
+			BIN_TO_BCD(real_minutes);
+		}
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else
+		retval = -1;
+
+	/* The following flags have to be released exactly in this order,
+	 * otherwise the DS12887 (popular MC146818A clone with integrated
+	 * battery and quartz) will not reset the oscillator and will not
+	 * update precisely 500 ms later. You won't find this mentioned in
+	 * the Dallas Semiconductor data sheets, but who believes data
+	 * sheets anyway ...                           -- Markus Kuhn
+	 */
+	CMOS_WRITE(save_control, RTC_CONTROL);
+	CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
+
+	return retval;
+}
+
 /*
  * We don't have a RTC to update!
  */
-#define update_rtc()
+extern __inline__ void update_rtc(void)
+{
+	static long last_rtc_update = 0;	/* last time the cmos clock got updated */
+
+	/* If we have an externally synchronized linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes.  Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec > 50000 - (tick >> 1) &&
+	    xtime.tv_usec < 50000 + (tick >> 1)) {
+		if (set_rtc_mmss(xtime.tv_sec) == 0)
+			last_rtc_update = xtime.tv_sec;
+		else
+			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+	}
+}
+
+extern __inline__ unsigned long get_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	// check to see if the RTC makes sense.....
+	if ((CMOS_READ(RTC_VALID) & RTC_VRT) == 0)
+		return mktime(1970, 1, 1, 0, 0, 0);
+
+	/* The Linux interpretation of the CMOS clock register contents:
+	 * When the Update-In-Progress (UIP) flag goes from 1 to 0, the
+	 * RTC registers show the second which has precisely just started.
+	 * Let's hope other operating systems interpret the RTC the same way.
+	 */
+	/* read RTC exactly on falling edge of update flag */
+	for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */
+		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)
+			break;
+
+	for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */
+		if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP))
+			break;
+
+	do { /* Isn't this overkill ? UIP above should guarantee consistency */
+		sec = CMOS_READ(RTC_SECONDS);
+		min = CMOS_READ(RTC_MINUTES);
+		hour = CMOS_READ(RTC_HOURS);
+		day = CMOS_READ(RTC_DAY_OF_MONTH);
+		mon = CMOS_READ(RTC_MONTH);
+		year = CMOS_READ(RTC_YEAR);
+	} while (sec != CMOS_READ(RTC_SECONDS));
+
+	if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
+		BCD_TO_BIN(sec);
+		BCD_TO_BIN(min);
+		BCD_TO_BIN(hour);
+		BCD_TO_BIN(day);
+		BCD_TO_BIN(mon);
+		BCD_TO_BIN(year);
+	}
+	if ((year += 1900) < 1970)
+		year += 100;
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+#define mSEC_10_from_14 ((14318180 + 100) / 200)
 
 /*
  * Set up timer interrupt, and return the current time in seconds.
  */
 extern __inline__ unsigned long setup_timer (void)
 {
-	*CSR_TIMER1_CLR  = 1;
-	*CSR_TIMER1_LOAD = LATCH;
-	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+	unsigned int c;
+
+	/* Turn on the RTC */
+	outb(13, 0x70);
+	if ((inb(0x71) & 0x80) == 0)
+		printk("RTC: *** warning: CMOS battery bad\n");
+
+	outb(10, 0x70);		/* select control reg */
+	outb(32, 0x71);		/* make sure the divider is set */
+	outb(11, 0x70);		/* select other control reg */
+	c = inb(0x71) & 0xfb;	/* read it */
+	outb(11, 0x70);
+	outb(c | 2, 0x71);	/* turn on BCD counting and 24 hour clock mode */
+	
+	/* enable PIT timer */
+	/* set for periodic (4) and LSB/MSB write (0x30) */
+	outb(0x34, 0x43);
+	outb((mSEC_10_from_14/6) & 0xFF, 0x40);
+	outb((mSEC_10_from_14/6) >> 8, 0x40);
 
 	/*
 	 * Default the date to 1 Jan 1970 00:00:00
 	 * You will have to run a time daemon to set the
 	 * clock correctly at bootup
 	 */
-	return mktime(1970, 1, 1, 0, 0, 0);
+	return get_cmos_time();
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/byteorder.h linux/include/asm-arm/byteorder.h
--- v2.1.131/linux/include/asm-arm/byteorder.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/byteorder.h	Thu Dec 17 09:05:43 1998
@@ -3,7 +3,10 @@
 
 #include <asm/types.h>
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ < 80
+
+/* Recent versions of GCC can do as well or better than this
+   on their own - we shouldn't interfere.  */
 
 static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
 {
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/dec21285.h linux/include/asm-arm/dec21285.h
--- v2.1.131/linux/include/asm-arm/dec21285.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/dec21285.h	Thu Dec 17 09:05:43 1998
@@ -0,0 +1,127 @@
+/*
+ * include/asm-arm/dec21285.h
+ *
+ * Copyright (C) 1998 Russell King
+ */
+#define DC21285_PCI_IACK		0x79000000
+#define DC21285_ARMCSR_BASE		0x42000000
+#define DC21285_PCI_TYPE_0_CONFIG	0x7b000000
+#define DC21285_PCI_TYPE_1_CONFIG	0x7a000000
+#define DC21285_OUTBOUND_WRITE_FLUSH	0x78000000
+#define DC21285_FLASH			0x41000000
+#define DC21285_PCI_IO			0x7c000000
+#define DC21285_PCI_MEM			0x80000000
+
+#ifndef __ASSEMBLY__
+
+/*
+ * DEC21285
+ */
+#define CSR_SA110_CNTL		((volatile unsigned long *)0xfe00013c)
+#define CSR_PCIADDR_EXTN	((volatile unsigned long *)0xfe000140)
+#define CSR_PREFETCHMEMRANGE	((volatile unsigned long *)0xfe000144)
+#define CSR_XBUS_CYCLE		((volatile unsigned long *)0xfe000148)
+#define CSR_XBUS_IOSTROBE	((volatile unsigned long *)0xfe00014c)
+#define CSR_DOORBELL_PCI	((volatile unsigned long *)0xfe000150)
+#define CSR_DOORBELL_SA110	((volatile unsigned long *)0xfe000154)
+
+#define CSR_UARTDR		((volatile unsigned long *)0xfe000160)
+#define CSR_RXSTAT		((volatile unsigned long *)0xfe000164)
+#define CSR_H_UBRLCR		((volatile unsigned long *)0xfe000168)
+#define CSR_M_UBRLCR		((volatile unsigned long *)0xfe00016c)
+#define CSR_L_UBRLCR		((volatile unsigned long *)0xfe000170)
+#define CSR_UARTCON		((volatile unsigned long *)0xfe000174)
+#define CSR_UARTFLG		((volatile unsigned long *)0xfe000178)
+
+#define CSR_IRQ_STATUS		((volatile unsigned long *)0xfe000180)
+#define CSR_IRQ_RAWSTATUS	((volatile unsigned long *)0xfe000184)
+#define CSR_IRQ_ENABLE		((volatile unsigned long *)0xfe000188)
+#define CSR_IRQ_DISABLE		((volatile unsigned long *)0xfe00018c)
+#define CSR_IRQ_SOFT		((volatile unsigned long *)0xfe000190)
+
+#define CSR_FIQ_STATUS		((volatile unsigned long *)0xfe000280)
+#define CSR_FIQ_RAWSTATUS	((volatile unsigned long *)0xfe000284)
+#define CSR_FIQ_ENABLE		((volatile unsigned long *)0xfe000288)
+#define CSR_FIQ_DISABLE		((volatile unsigned long *)0xfe00028c)
+#define CSR_FIQ_SOFT		((volatile unsigned long *)0xfe000290)
+
+#define CSR_TIMER1_LOAD		((volatile unsigned long *)0xfe000300)
+#define CSR_TIMER1_VALUE	((volatile unsigned long *)0xfe000304)
+#define CSR_TIMER1_CNTL		((volatile unsigned long *)0xfe000308)
+#define CSR_TIMER1_CLR		((volatile unsigned long *)0xfe00030c)
+
+#define CSR_TIMER2_LOAD		((volatile unsigned long *)0xfe000320)
+#define CSR_TIMER2_VALUE	((volatile unsigned long *)0xfe000324)
+#define CSR_TIMER2_CNTL		((volatile unsigned long *)0xfe000328)
+#define CSR_TIMER2_CLR		((volatile unsigned long *)0xfe00032c)
+
+#define CSR_TIMER3_LOAD		((volatile unsigned long *)0xfe000340)
+#define CSR_TIMER3_VALUE	((volatile unsigned long *)0xfe000344)
+#define CSR_TIMER3_CNTL		((volatile unsigned long *)0xfe000348)
+#define CSR_TIMER3_CLR		((volatile unsigned long *)0xfe00034c)
+
+#define CSR_TIMER4_LOAD		((volatile unsigned long *)0xfe000360)
+#define CSR_TIMER4_VALUE	((volatile unsigned long *)0xfe000364)
+#define CSR_TIMER4_CNTL		((volatile unsigned long *)0xfe000368)
+#define CSR_TIMER4_CLR		((volatile unsigned long *)0xfe00036c)
+
+#else
+
+#define CSR_SA110_CNTL		0x13c
+#define CSR_PCIADDR_EXTN	0x140
+#define CSR_PREFETCHMEMRANGE	0x144
+#define CSR_XBUS_CYCLE		0x148
+#define CSR_XBUS_IOSTROBE	0x14c
+#define CSR_DOORBELL_PCI	0x150
+#define CSR_DOORBELL_SA110	0x154
+
+#define CSR_UARTDR		0x160
+#define CSR_RXSTAT		0x164
+#define CSR_H_UBRLCR		0x168
+#define CSR_M_UBRLCR		0x16c
+#define CSR_L_UBRLCR		0x170
+#define CSR_UARTCON		0x174
+#define CSR_UARTFLG		0x178
+
+#define CSR_IRQ_STATUS		0x180
+#define CSR_IRQ_RAWSTATUS	0x184
+#define CSR_IRQ_ENABLE		0x188
+#define CSR_IRQ_DISABLE		0x18c
+#define CSR_IRQ_SOFT		0x190
+
+#define CSR_FIQ_STATUS		0x280
+#define CSR_FIQ_RAWSTATUS	0x284
+#define CSR_FIQ_ENABLE		0x288
+#define CSR_FIQ_DISABLE		0x28c
+#define CSR_FIQ_SOFT		0x290
+
+#define CSR_TIMER1_LOAD		0x300
+#define CSR_TIMER1_VALUE	0x304
+#define CSR_TIMER1_CNTL		0x308
+#define CSR_TIMER1_CLR		0x30c
+
+#define CSR_TIMER2_LOAD		0x320
+#define CSR_TIMER2_VALUE	0x324
+#define CSR_TIMER2_CNTL		0x328
+#define CSR_TIMER2_CLR		0x32c
+
+#define CSR_TIMER3_LOAD		0x340
+#define CSR_TIMER3_VALUE	0x344
+#define CSR_TIMER3_CNTL		0x348
+#define CSR_TIMER3_CLR		0x34c
+
+#define CSR_TIMER4_LOAD		0x360
+#define CSR_TIMER4_VALUE	0x364
+#define CSR_TIMER4_CNTL		0x368
+#define CSR_TIMER4_CLR		0x36c
+
+#endif
+
+#define TIMER_CNTL_ENABLE	(1 << 7)
+#define TIMER_CNTL_AUTORELOAD	(1 << 6)
+#define TIMER_CNTL_DIV1		(0)
+#define TIMER_CNTL_DIV16	(1 << 2)
+#define TIMER_CNTL_DIV256	(2 << 2)
+#define TIMER_CNTL_CNTEXT	(3 << 2)
+
+
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/dma.h linux/include/asm-arm/dma.h
--- v2.1.131/linux/include/asm-arm/dma.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/dma.h	Thu Dec 17 09:05:43 1998
@@ -4,6 +4,7 @@
 typedef unsigned int dmach_t;
 
 #include <asm/irq.h>
+#include <asm/spinlock.h>
 #include <asm/arch/dma.h>
 
 typedef struct {
@@ -13,6 +14,20 @@
 
 extern const char dma_str[];
 
+extern spinlock_t  dma_spin_lock;
+
+extern __inline__ unsigned long claim_dma_lock(void)
+{
+	unsigned long flags;
+	spin_lock_irqsave(&dma_spin_lock, flags);
+	return flags;
+}
+
+extern __inline__ void release_dma_lock(unsigned long flags)
+{
+	spin_unlock_irqrestore(&dma_spin_lock, flags);
+}
+
 /* Clear the 'DMA Pointer Flip Flop'.
  * Write 0 for LSB/MSB, 1 for MSB/LSB access.
  *
@@ -26,7 +41,7 @@
  * NOTE: This is an architecture specific function, and should
  *       be hidden from the drivers
  */
-static __inline__ void set_dma_page(dmach_t channel, char pagenr)
+extern __inline__ void set_dma_page(dmach_t channel, char pagenr)
 {
 	printk(dma_str, "set_dma_page", channel);
 }
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/ecard.h linux/include/asm-arm/ecard.h
--- v2.1.131/linux/include/asm-arm/ecard.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/ecard.h	Thu Dec 17 09:05:43 1998
@@ -31,6 +31,9 @@
 #define MANU_ATOMWIDE		0x0017
 #define PROD_ATOMWIDE_3PSERIAL		0x0090
 
+#define MANU_IRLAM_INSTRUMENTS	0x001f
+#define MANU_IRLAM_INSTRUMENTS_ETHERN	0x5678
+
 #define MANU_OAK		0x0021
 #define PROD_OAK_SCSI			0x0058
 
@@ -75,51 +78,48 @@
 
 #define MAX_ECARDS	8
 
-/* Type of card's address space */
-typedef enum {
+typedef enum {				/* Cards address space		*/
 	ECARD_IOC,
 	ECARD_MEMC,
-	ECARD_DEBI
+	ECARD_EASI
 } card_type_t;
 
-/* Speed of card for ECARD_IOC address space */
-typedef enum {
+typedef enum {				/* Speed for ECARD_IOC space	*/
 	ECARD_SLOW	 = 0,
 	ECARD_MEDIUM	 = 1,
 	ECARD_FAST	 = 2,
 	ECARD_SYNC	 = 3
 } card_speed_t;
 
-/* Card ID structure */
-typedef struct  {
+typedef struct  {			/* Card ID structure		*/
 	unsigned short manufacturer;
 	unsigned short product;
 } card_ids;
 
-/* External view of card ID information */
-struct in_ecld {
-	unsigned short	product;
-	unsigned short	manufacturer;
-	unsigned char	ecld;
-	unsigned char	country;
-	unsigned char	fiqmask;
-	unsigned char	irqmask;
-	unsigned long	fiqaddr;
-	unsigned long	irqaddr;
+struct in_ecid {			/* Packed card ID information	*/
+	unsigned short	product;	/* Product code			*/
+	unsigned short	manufacturer;	/* Manufacturer code		*/
+	unsigned char	id:4;		/* Simple ID			*/
+	unsigned char	cd:1;		/* Chunk dir present		*/
+	unsigned char	is:1;		/* Interrupt status pointers	*/
+	unsigned char	w:2;		/* Width			*/
+	unsigned char	country;	/* Country			*/
+	unsigned char	irqmask;	/* IRQ mask			*/
+	unsigned char	fiqmask;	/* FIQ mask			*/
+	unsigned long	irqoff;		/* IRQ offset			*/
+	unsigned long	fiqoff;		/* FIQ offset			*/
 };
 
 typedef struct expansion_card ecard_t;
+typedef unsigned long *loader_t;
 
-/* Card handler routines */
-typedef struct {
+typedef struct {			/* Card handler routines	*/
 	void (*irqenable)(ecard_t *ec, int irqnr);
 	void (*irqdisable)(ecard_t *ec, int irqnr);
 	void (*fiqenable)(ecard_t *ec, int fiqnr);
 	void (*fiqdisable)(ecard_t *ec, int fiqnr);
 } expansioncard_ops_t;
 
-typedef unsigned long *loader_t;
-
 /*
  * This contains all the info needed on an expansion card
  */
@@ -131,17 +131,19 @@
 	unsigned char		fiqmask;	/* FIQ mask			*/
 	unsigned char  		claimed;	/* Card claimed?		*/
 
+	void			*irq_data;	/* Data for use for IRQ by card	*/
+	void			*fiq_data;	/* Data for use for FIQ by card	*/
+	expansioncard_ops_t	*ops;		/* Enable/Disable Ops for card	*/
+
 	CONST unsigned char	slot_no;	/* Slot number			*/
 	CONST unsigned char	dma;		/* DMA number (for request_dma)	*/
 	CONST unsigned char	irq;		/* IRQ number (for request_irq)	*/
 	CONST unsigned char	fiq;		/* FIQ number (for request_irq)	*/
-
-	CONST struct in_ecld	cld;		/* Card Identification		*/
-	void			*irq_data;	/* Data for use for IRQ by card	*/
-	void			*fiq_data;	/* Data for use for FIQ by card	*/
-	expansioncard_ops_t	*ops;		/* Enable/Disable Ops for card	*/
+	CONST card_type_t	type;		/* Type of card			*/
+	CONST struct in_ecid	cid;		/* Card Identification		*/
 
 	/* Private internal data */
+	const char		*card_desc;	/* Card description		*/
 	CONST unsigned int	podaddr;	/* Base Linux address for card	*/
 	CONST loader_t		loader;		/* loader program */
 };
@@ -170,9 +172,9 @@
 extern void ecard_startfind (void);
 
 /*
- * Find an expansion card with the correct cld, product and manufacturer code
+ * Find an expansion card with the correct cid, product and manufacturer code
  */
-extern struct expansion_card *ecard_find (int cld, const card_ids *ids);
+extern struct expansion_card *ecard_find (int cid, const card_ids *ids);
  
 /*
  * Read a chunk from an expansion card
@@ -193,25 +195,31 @@
  *
  * External expansion card header as read from the card
  */
-struct ex_ecld {
-	unsigned char  r_ecld;
-	unsigned char  r_reserved[2];
-	unsigned char  r_product[2];
-	unsigned char  r_manufacturer[2];
-	unsigned char  r_country;
-	         long  r_fiqs;
-	         long  r_irqs;
-#define e_ecld(x)	((x)->r_ecld)
-#define e_cd(x)		((x)->r_reserved[0] & 1)
-#define e_is(x)		((x)->r_reserved[0] & 2)
-#define e_w(x)		(((x)->r_reserved[0] & 12)>>2)
-#define e_prod(x)	((x)->r_product[0]|((x)->r_product[1]<<8))
-#define e_manu(x)	((x)->r_manufacturer[0]|((x)->r_manufacturer[1]<<8))
-#define e_country(x)	((x)->r_country)
-#define e_fiqmask(x)	((x)->r_fiqs & 0xff)
-#define e_fiqaddr(x)	((x)->r_fiqs >> 8)
-#define e_irqmask(x)	((x)->r_irqs & 0xff)
-#define e_irqaddr(x)	((x)->r_irqs >> 8)
+struct ex_ecid {
+	unsigned char	r_irq:1;
+	unsigned char	r_zero:1;
+	unsigned char	r_fiq:1;
+	unsigned char	r_id:4;
+	unsigned char	r_a:1;
+
+	unsigned char	r_cd:1;
+	unsigned char	r_is:1;
+	unsigned char	r_w:2;
+	unsigned char	r_r1:4;
+
+	unsigned char	r_r2:8;
+
+	unsigned char	r_prod[2];
+
+	unsigned char	r_manu[2];
+
+	unsigned char	r_country;
+
+	unsigned char	r_irqmask;
+	unsigned char	r_irqoff[3];
+
+	unsigned char	r_fiqmask;
+	unsigned char	r_fiqoff[3];
 };
 
 /*
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/elf.h linux/include/asm-arm/elf.h
--- v2.1.131/linux/include/asm-arm/elf.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/elf.h	Thu Dec 17 09:05:43 1998
@@ -6,6 +6,7 @@
  */
 
 #include <asm/ptrace.h>
+#include <asm/proc/elf.h>
 #include <asm/procinfo.h>
 
 typedef unsigned long elf_greg_t;
@@ -20,7 +21,7 @@
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-#define elf_check_arch(x) ( ((x) == EM_ARM) )
+#define elf_check_arch(x) ( ((x)->e_machine == EM_ARM) && (ELF_PROC_OK((x))) )
 
 /*
  * These are used to set parameters in the core dumps.
@@ -30,7 +31,6 @@
 #define ELF_ARCH	EM_ARM
 
 #define USE_ELF_CORE_DUMP
-#define ELF_EXEC_PAGESIZE	4096
 
 /* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
    use of this is to invoke "./ld.so someprog" to test out a new version of
@@ -64,10 +64,5 @@
 #define ELF_PLATFORM_SIZE 8
 extern char elf_platform[];
 #define ELF_PLATFORM	(elf_platform)
-
-#ifdef __KERNEL__
-#define SET_PERSONALITY(ex,ibcs2) \
-	current->personality = PER_LINUX_32BIT
-#endif
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/hardware.h linux/include/asm-arm/hardware.h
--- v2.1.131/linux/include/asm-arm/hardware.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/hardware.h	Thu Dec 17 09:05:43 1998
@@ -85,7 +85,7 @@
 
 #ifdef HAS_IOMD
 #ifndef __ASSEMBLER__
-#define __IOMD(offset)	(IOMD_BASE + (offset >> 2))
+#define __IOMD(offset)	(IO_IOMD_BASE + (offset >> 2))
 #else
 #define __IOMD(offset)	offset
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/ide.h linux/include/asm-arm/ide.h
--- v2.1.131/linux/include/asm-arm/ide.h	Thu May  7 22:51:54 1998
+++ linux/include/asm-arm/ide.h	Thu Dec 17 09:05:43 1998
@@ -13,8 +13,6 @@
 
 #ifdef __KERNEL__
 
-typedef unsigned long ide_ioreg_t;
-
 #ifndef MAX_HWIFS
 #define MAX_HWIFS	4
 #endif
@@ -34,51 +32,19 @@
 	} b;
 	} select_t;
 
-static __inline__ int ide_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
-			unsigned long flags, const char *device, void *dev_id)
-{
-	return request_irq(irq, handler, flags, device, dev_id);
-}			
-
-static __inline__ void ide_free_irq(unsigned int irq, void *dev_id)
-{
-	free_irq(irq, dev_id);
-}
-
-static __inline__ int ide_check_region (ide_ioreg_t from, unsigned int extent)
-{
-	return check_region(from, extent);
-}
-
-static __inline__ void ide_request_region (ide_ioreg_t from, unsigned int extent, const char *name)
-{
-	request_region(from, extent, name);
-}
-
-static __inline__ void ide_release_region (ide_ioreg_t from, unsigned int extent)
-{
-	release_region(from, extent);
-}
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+#define ide_check_region(from,extent)		check_region((from), (extent))
+#define ide_request_region(from,extent,name)	request_region((from), (extent), (name))
+#define ide_release_region(from,extent)		release_region((from), (extent))
 
 /*
  * The following are not needed for the non-m68k ports
  */
-static __inline__ int ide_ack_intr (ide_ioreg_t status_port, ide_ioreg_t irq_port)
-{
-	return(1);
-}
-
-static __inline__ void ide_fix_driveid(struct hd_driveid *id)
-{
-}
-
-static __inline__ void ide_release_lock (int *ide_lock)
-{
-}
-
-static __inline__ void ide_get_lock (int *ide_lock, void (*handler)(int, void *, struct pt_regs *), void *data)
-{
-}
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/irq.h linux/include/asm-arm/irq.h
--- v2.1.131/linux/include/asm-arm/irq.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/irq.h	Thu Dec 17 09:05:43 1998
@@ -3,7 +3,9 @@
 
 #include <asm/arch/irqs.h>
 
+#ifndef irq_cannonicalize
 #define irq_cannonicalize(i)	(i)
+#endif
 
 #ifndef NR_IRQS
 #define NR_IRQS	128
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/keyboard.h linux/include/asm-arm/keyboard.h
--- v2.1.131/linux/include/asm-arm/keyboard.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/keyboard.h	Thu Dec 17 09:05:43 1998
@@ -19,8 +19,6 @@
 
 #include <asm/arch/keyboard.h>
 
-#define SYSRQ_KEY 13
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASM_ARM_KEYBOARD_H */
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/linux_logo.h linux/include/asm-arm/linux_logo.h
--- v2.1.131/linux/include/asm-arm/linux_logo.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/linux_logo.h	Thu Dec 17 09:05:43 1998
@@ -11,13 +11,16 @@
 
 #define linux_logo_banner "ARM Linux version " UTS_RELEASE
 
-#define LINUX_LOGO_COLORS	221
+#define LINUX_LOGO_COLORS	214
 
 #ifdef INCLUDE_LINUX_LOGO_DATA
 
+#define INCLUDE_LINUX_LOGOBW
 #define INCLUDE_LINUX_LOGO16
+
 #include <linux/linux_logo.h>
 
+#else
 
 /* prototypes only */
 extern unsigned char linux_logo_red[];
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/md.h linux/include/asm-arm/md.h
--- v2.1.131/linux/include/asm-arm/md.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/md.h	Thu Dec 17 09:05:43 1998
@@ -0,0 +1,13 @@
+/* $Id: md.h,v 1.1 1997/12/15 15:11:57 jj Exp $
+ * md.h: High speed xor_block operation for RAID4/5 
+ *
+ */
+ 
+#ifndef __ASM_MD_H
+#define __ASM_MD_H
+
+/* #define HAVE_ARCH_XORBLOCK */
+
+#define MD_XORBLOCK_ALIGNMENT	sizeof(long)
+
+#endif /* __ASM_MD_H */
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/posix_types.h linux/include/asm-arm/posix_types.h
--- v2.1.131/linux/include/asm-arm/posix_types.h	Fri May  8 23:14:54 1998
+++ linux/include/asm-arm/posix_types.h	Thu Dec 17 09:05:43 1998
@@ -1,7 +1,7 @@
 /*
  * linux/include/asm-arm/posix_types.h
  *
- * Copyright (c) 1996 Russell King.
+ * Copyright (c) 1996-1998 Russell King.
  *
  * Changelog:
  *  27-06-1996	RMK	Created
@@ -9,8 +9,6 @@
 #ifndef __ARCH_ARM_POSIX_TYPES_H
 #define __ARCH_ARM_POSIX_TYPES_H
 
-#include <linux/config.h>
-
 /*
  * This file is generally used by user-level software, so you need to
  * be a little careful about namespace pollution etc.  Also, we cannot
@@ -26,11 +24,7 @@
 typedef unsigned short		__kernel_ipc_pid_t;
 typedef unsigned short		__kernel_uid_t;
 typedef unsigned short		__kernel_gid_t;
-#ifdef CONFIG_BINUTILS_NEW
-typedef long unsigned int	__kernel_size_t;
-#else
 typedef unsigned int		__kernel_size_t;
-#endif
 typedef int			__kernel_ssize_t;
 typedef int			__kernel_ptrdiff_t;
 typedef long			__kernel_time_t;
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armo/elf.h linux/include/asm-arm/proc-armo/elf.h
--- v2.1.131/linux/include/asm-arm/proc-armo/elf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/proc-armo/elf.h	Thu Dec 17 09:05:43 1998
@@ -0,0 +1,19 @@
+/*
+ * ELF definitions for 26-bit CPUs
+ */
+
+#define ELF_EXEC_PAGESIZE	32768
+
+#if 0		/* not yet */
+#define ELF_PROC_OK(x)		\
+	((x)->e_flags & EF_ARM_APCS26)
+#else
+#define ELF_PROC_OK(x)		(1)
+#endif
+
+#ifdef __KERNEL__
+
+#define SET_PERSONALITY(ex,ibcs2) \
+	current->personality = PER_LINUX
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.1.131/linux/include/asm-arm/proc-armo/pgtable.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/proc-armo/pgtable.h	Thu Dec 17 09:05:43 1998
@@ -119,13 +119,6 @@
 #define PTRS_PER_PGD    32
 #define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)
 
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
- * current 8MB value just means that there will be a 8MB "hole" after the
- * physical memory until the kernel virtual memory starts.  That means that
- * any out-of-bounds memory accesses will hopefully be caught.
- * The vmalloc() routines leaves a hole of 4kB between each vmalloced
- * area for the same reason. ;)
- */
 #define VMALLOC_START	0x01a00000
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END	0x01c00000
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armo/processor.h linux/include/asm-arm/proc-armo/processor.h
--- v2.1.131/linux/include/asm-arm/proc-armo/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/proc-armo/processor.h	Thu Dec 17 09:05:43 1998
@@ -9,6 +9,7 @@
  *  26-09-1996	RMK	Added 'EXTRA_THREAD_STRUCT*'
  *  28-09-1996	RMK	Moved start_thread into the processor dependencies
  *  11-01-1998	RMK	Added new uaccess_t
+ *  09-09-1998	PJB	Delete redundant `wp_works_ok'
  */
 #ifndef __ASM_PROC_PROCESSOR_H
 #define __ASM_PROC_PROCESSOR_H
@@ -19,12 +20,6 @@
 #include <linux/string.h>
 
 #define KERNEL_STACK_SIZE 4096
-
-/*
- * on arm2,3 wp does not work
- */
-#define wp_works_ok 0
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
 
 struct context_save_struct {
 	unsigned long r4;
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armo/system.h linux/include/asm-arm/proc-armo/system.h
--- v2.1.131/linux/include/asm-arm/proc-armo/system.h	Tue Jan 20 16:39:42 1998
+++ linux/include/asm-arm/proc-armo/system.h	Thu Dec 17 09:05:43 1998
@@ -19,6 +19,7 @@
 		case 4:	return processor.u.armv2._xchg_4(x, ptr);
 		default: arm_invalidptr(xchg_str, size);
 	}
+	return 0;
 }
 
 /*
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armv/elf.h linux/include/asm-arm/proc-armv/elf.h
--- v2.1.131/linux/include/asm-arm/proc-armv/elf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/proc-armv/elf.h	Thu Dec 17 09:05:43 1998
@@ -0,0 +1,21 @@
+/*
+ * ELF definitions for 32-bit CPUs
+ */
+
+#define ELF_EXEC_PAGESIZE	4096
+
+/* We can execute both 32-bit and 26-bit code. */
+#define ELF_PROC_OK(x)		(1)
+
+#ifdef __KERNEL__
+
+#if 0		/* not yet */
+#define SET_PERSONALITY(ex,ibcs2) \
+	current_personality = (ex->e_flags & EF_ARM_APCS26) ? \
+	PER_LINUX : PER_LINUX_32BIT
+#else
+#define SET_PERSONALITY(ex,ibcs2) \
+	current->personality = PER_LINUX_32BIT
+#endif
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armv/io.h linux/include/asm-arm/proc-armv/io.h
--- v2.1.131/linux/include/asm-arm/proc-armv/io.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/proc-armv/io.h	Thu Dec 17 09:05:43 1998
@@ -22,17 +22,17 @@
 
 #include <asm/proc-fns.h>
 
-#define dma_cache_inv(_start,_size)						\
-	do {									\
-		processor.u.armv3v4._cache_purge_area(_start,(_start+_size));	\
-	} while (0)
+extern inline void dma_cache_inv(unsigned long start, unsigned long size)
+{
+	processor.u.armv3v4._cache_purge_area(start, start + size);
+}
 
-#define dma_cache_wback(_start,_size)						\
-	do {									\
-		processor.u.armv3v4._cache_wback_area(_start,(_start+_size));	\
-	} while (0)
+extern inline void dma_cache_wback(unsigned long start, unsigned long size)
+{
+	processor.u.armv3v4._cache_wback_area(start, start + size);
+}
 
-#define dma_cache_wback_inv(_start,_size)					\
-	do {									\
-		processor.u.armv3v4._flush_cache_area(_start,(_start+_size),0);	\
-	} while (0)
+extern inline void dma_cache_wback_inv(unsigned long start, unsigned long size)
+{
+	processor.u.armv3v4._flush_cache_area(start, start + size, 0);
+}
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armv/processor.h linux/include/asm-arm/proc-armv/processor.h
--- v2.1.131/linux/include/asm-arm/proc-armv/processor.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/proc-armv/processor.h	Thu Dec 17 09:05:43 1998
@@ -7,6 +7,7 @@
  *  20-09-1996	RMK	Created
  *  26-09-1996	RMK	Added 'EXTRA_THREAD_STRUCT*'
  *  28-09-1996	RMK	Moved start_thread into the processor dependencies
+ *  09-09-1998	PJB	Delete redundant `wp_works_ok'
  */
 #ifndef __ASM_PROC_PROCESSOR_H
 #define __ASM_PROC_PROCESSOR_H
@@ -14,12 +15,6 @@
 #ifdef __KERNEL__
  
 #define KERNEL_STACK_SIZE	PAGE_SIZE
-
-/*
- * on arm2,3 wp does not work
- */
-#define wp_works_ok 0
-#define wp_works_ok__is_a_macro /* for versions in ksyms.c */
 
 struct context_save_struct {
 	unsigned long cpsr;
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/proc-armv/uaccess.h linux/include/asm-arm/proc-armv/uaccess.h
--- v2.1.131/linux/include/asm-arm/proc-armv/uaccess.h	Tue Jan 20 16:39:43 1998
+++ linux/include/asm-arm/proc-armv/uaccess.h	Thu Dec 17 09:05:43 1998
@@ -11,6 +11,8 @@
  *  DOMAIN_USER   - domain 0 includes all user memory only
  */
 
+#include <asm/hardware.h>
+
 #define DOMAIN_CLIENT	1
 #define DOMAIN_MANAGER	3
  
@@ -35,7 +37,7 @@
  * Note that this is actually 0x1,0000,0000
  */
 #define KERNEL_DS	0x00000000
-#define USER_DS		0xc0000000
+#define USER_DS		PAGE_OFFSET
 
 #define get_ds()	(KERNEL_DS)
 #define get_fs()	(current->addr_limit)
@@ -50,13 +52,10 @@
 		: "r" (fs ? USER_DOMAIN : KERNEL_DOMAIN));
 }
 
-/*
- * a + s   <= 2^32  -> C = 0 || Z = 0 (LS)
- * (a + s) <= l     -> C = 0 || Z = 0 (LS)
- */
+/* We use 33-bit arithmetic here... */
 #define __range_ok(addr,size) ({ \
 	unsigned long flag, sum; \
-	__asm__ __volatile__("adds %1, %2, %3; cmpls %1, %0; movls %0, #0" \
+	__asm__ __volatile__("adds %1, %2, %3; sbccs %1, %1, %0; movcc %0, #0" \
 		: "=&r" (flag), "=&r" (sum) \
 		: "r" (addr), "Ir" (size), "0" (current->addr_limit) \
 		: "cc"); \
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/signal.h linux/include/asm-arm/signal.h
--- v2.1.131/linux/include/asm-arm/signal.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/signal.h	Thu Dec 17 09:05:43 1998
@@ -132,6 +132,7 @@
 #define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
 #define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
 
+#ifdef __KERNEL__
 struct old_sigaction {
 	__sighandler_t sa_handler;
 	old_sigset_t sa_mask;
@@ -149,6 +150,24 @@
 struct k_sigaction {
 	struct sigaction sa;
 };
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
 
 typedef struct sigaltstack {
 	void *ss_sp;
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/socket.h linux/include/asm-arm/socket.h
--- v2.1.131/linux/include/asm-arm/socket.h	Tue Apr 14 14:29:25 1998
+++ linux/include/asm-arm/socket.h	Thu Dec 17 09:05:43 1998
@@ -35,4 +35,8 @@
 
 #define SO_BINDTODEVICE 25
 
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
 #endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/spinlock.h linux/include/asm-arm/spinlock.h
--- v2.1.131/linux/include/asm-arm/spinlock.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/spinlock.h	Thu Dec 17 09:05:43 1998
@@ -37,8 +37,13 @@
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
  */
-typedef struct { } rwlock_t;
-#define RW_LOCK_UNLOCKED { }
+#if (__GNUC__ > 2) || (__GNUC_MINOR__ >= 8)
+  typedef struct { } rwlock_t;
+# define RW_LOCK_UNLOCKED { }
+#else
+  typedef unsigned char rwlock_t;
+# define RW_LOCK_UNLOCKED 0
+#endif
 
 #define read_lock(lock)		do { } while(0)
 #define read_unlock(lock)	do { } while(0)
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/system.h linux/include/asm-arm/system.h
--- v2.1.131/linux/include/asm-arm/system.h	Wed Sep  9 14:51:12 1998
+++ linux/include/asm-arm/system.h	Thu Dec 17 09:05:43 1998
@@ -1,6 +1,8 @@
 #ifndef __ASM_ARM_SYSTEM_H
 #define __ASM_ARM_SYSTEM_H
 
+#include <linux/config.h>
+
 /* The type of machine we're running on */
 extern unsigned int machine_type;
 #define MACH_TYPE_EBSA110	0
@@ -10,6 +12,29 @@
 #define MACH_TYPE_NETWINDER	5
 #define MACH_TYPE_CATS		6
 #define MACH_TYPE_TBOX		7
+
+#ifdef CONFIG_ARCH_EBSA285
+#define machine_is_ebsa285()	(1)
+#else
+#define machine_is_ebsa285()	(0)
+#endif
+
+#ifdef CONFIG_ARCH_VNC
+#define machine_is_netwinder()	(1)
+#else
+#define machine_is_netwinder()	(0)
+#endif
+
+#if defined(CONFIG_CATS)
+#define machine_is_cats()	(machine_type == MACH_TYPE_CATS)
+#else
+#define machine_is_cats()	(0)
+#endif
+
+#if 0
+#define machine_is_ebsa285()	(machine_type == MACH_TYPE_EBSA285)
+#define machine_is_netwinder()	(machine_type == MACH_TYPE_NETWINDER)
+#endif
 
 #include <linux/kernel.h>
 #include <asm/proc-fns.h>
diff -u --recursive --new-file v2.1.131/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h
--- v2.1.131/linux/include/asm-arm/termios.h	Mon Oct  5 13:13:42 1998
+++ linux/include/asm-arm/termios.h	Wed Dec 16 13:35:49 1998
@@ -58,6 +58,8 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-i386/dma.h linux/include/asm-i386/dma.h
--- v2.1.131/linux/include/asm-i386/dma.h	Thu Nov 12 16:21:24 1998
+++ linux/include/asm-i386/dma.h	Tue Dec 22 10:44:30 1998
@@ -8,6 +8,7 @@
 #ifndef _ASM_DMA_H
 #define _ASM_DMA_H
 
+#include <linux/config.h>
 #include <asm/io.h>		/* need byte IO */
 #include <asm/spinlock.h>	/* And spinlocks */
 #include <linux/delay.h>
@@ -284,5 +285,12 @@
 extern int request_dma(unsigned int dmanr, const char * device_id);	/* reserve a DMA channel */
 extern void free_dma(unsigned int dmanr);	/* release it again */
 
+/* From PCI */
+
+#ifdef CONFIG_PCI_QUIRKS
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy 	(0)
+#endif
 
 #endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.1.131/linux/include/asm-i386/mca_dma.h linux/include/asm-i386/mca_dma.h
--- v2.1.131/linux/include/asm-i386/mca_dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/mca_dma.h	Thu Dec 17 09:06:24 1998
@@ -0,0 +1,126 @@
+#ifndef MCA_DMA_H
+#define MCA_DMA_H
+
+#include <asm/io.h>
+#include <linux/ioport.h>
+
+/*
+ * Microchannel specific DMA stuff.  DMA on an MCA machine is fairly similar to
+ *   standard PC dma, but it certainly has its quirks.  DMA register addresses
+ *   are in a different place and there are some added functions.  Most of this
+ *   should be pretty obvious on inspection.  Note that the user must divide
+ *   count by 2 when using 16-bit dma; that is not handled by these functions.
+ *
+ * Ramen Noodles are yummy.
+ * 
+ *  1998 Tymm Twillman <tymm@computer.org>  
+ */
+
+/*
+ * Registers that are used by the DMA controller; FN is the function register 
+ *   (tell the controller what to do) and EXE is the execution register (how
+ *   to do it)
+ */
+
+#define MCA_DMA_REG_FN  0x18
+#define MCA_DMA_REG_EXE 0x1A 
+
+/*
+ * Functions that the DMA controller can do
+ */
+
+#define MCA_DMA_FN_SET_IO       0x00
+#define MCA_DMA_FN_SET_ADDR     0x20
+#define MCA_DMA_FN_GET_ADDR     0x30
+#define MCA_DMA_FN_SET_COUNT    0x40
+#define MCA_DMA_FN_GET_COUNT    0x50
+#define MCA_DMA_FN_GET_STATUS   0x60
+#define MCA_DMA_FN_SET_MODE     0x70
+#define MCA_DMA_FN_SET_ARBUS    0x80
+#define MCA_DMA_FN_MASK         0x90
+#define MCA_DMA_FN_RESET_MASK   0xA0
+#define MCA_DMA_FN_MASTER_CLEAR 0xD0
+
+/*
+ * Modes (used by setting MCA_DMA_FN_MODE in the function register)
+ * 
+ * Note that the MODE_READ is read from memory (write to device), and
+ *   MODE_WRITE is vice-versa.  
+ */
+
+#define MCA_DMA_MODE_XFER  0x04  /* read by default */
+#define MCA_DMA_MODE_READ  0x04  /* same as XFER */
+#define MCA_DMA_MODE_WRITE 0x08  /* OR with MODE_XFER to use */
+#define MCA_DMA_MODE_IO    0x01  /* DMA from IO register */
+#define MCA_DMA_MODE_16    0x40  /* 16 bit xfers */
+
+
+
+static __inline__ void mca_enable_dma(unsigned int dmanr)
+{
+	outb(MCA_DMA_FN_RESET_MASK | dmanr, MCA_DMA_REG_FN);
+}
+
+static __inline__ void mca_disable_dma(unsigned int dmanr)
+{
+	outb(MCA_DMA_FN_MASK | dmanr, MCA_DMA_REG_FN);
+}
+
+static __inline__ void mca_set_dma_addr(unsigned int dmanr, unsigned int a)
+{
+	outb(MCA_DMA_FN_SET_ADDR | dmanr, MCA_DMA_REG_FN);
+	outb(a & 0xff, MCA_DMA_REG_EXE);
+	outb((a >> 8) & 0xff, MCA_DMA_REG_EXE);
+	outb((a >> 16) & 0xff, MCA_DMA_REG_EXE);
+}
+
+static __inline__ unsigned int mca_get_dma_addr(unsigned int dmanr)
+{
+	unsigned int addr;
+
+	outb(MCA_DMA_FN_GET_ADDR | dmanr, MCA_DMA_REG_FN);
+	addr = inb(MCA_DMA_REG_EXE);
+	addr |= inb(MCA_DMA_REG_EXE) << 8;
+	addr |= inb(MCA_DMA_REG_EXE) << 16;  
+
+	return addr;
+}
+
+static __inline__ void mca_set_dma_count(unsigned int dmanr, unsigned int count)
+{
+	count--;  /* transfers one more than count -- correct for this */
+
+	outb(MCA_DMA_FN_SET_COUNT | dmanr, MCA_DMA_REG_FN);
+	outb(count & 0xff, MCA_DMA_REG_EXE);
+	outb((count >> 8) & 0xff, MCA_DMA_REG_EXE);
+}
+
+static __inline__ unsigned int mca_get_dma_residue(unsigned int dmanr)
+{
+	unsigned short count;
+
+	outb(MCA_DMA_FN_GET_COUNT | dmanr, MCA_DMA_REG_FN);
+	count = 1 + inb(MCA_DMA_REG_EXE);
+	count += inb(MCA_DMA_REG_EXE) << 8;
+
+	return count;
+}
+
+static __inline__ void mca_set_dma_io(unsigned int dmanr, unsigned int io_addr)
+{
+	/*
+	 * DMA from a port address -- set the io address
+	 */
+	
+	outb(MCA_DMA_FN_SET_IO | dmanr, MCA_DMA_REG_FN);
+	outb(io_addr & 0xff, MCA_DMA_REG_EXE);
+	outb((io_addr >>  8) & 0xff, MCA_DMA_REG_EXE);
+}
+
+static __inline__ void mca_set_dma_mode(unsigned int dmanr, unsigned int mode)
+{
+	outb(MCA_DMA_FN_SET_MODE | dmanr, MCA_DMA_REG_FN);
+	outb(mode, MCA_DMA_REG_EXE);
+}
+
+#endif MCA_DMA_H
diff -u --recursive --new-file v2.1.131/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.1.131/linux/include/asm-i386/smp.h	Thu Aug  6 14:06:33 1998
+++ linux/include/asm-i386/smp.h	Tue Dec 22 10:44:25 1998
@@ -237,7 +237,7 @@
  *	processes are run.
  */
  
-#define PROC_CHANGE_PENALTY	20		/* Schedule penalty */
+#define PROC_CHANGE_PENALTY	10		/* Schedule penalty */
 
 #define SMP_FROM_INT		1
 #define SMP_FROM_SYSCALL	2
diff -u --recursive --new-file v2.1.131/linux/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
--- v2.1.131/linux/include/asm-i386/softirq.h	Thu Aug 27 19:56:30 1998
+++ linux/include/asm-i386/softirq.h	Tue Dec 22 10:44:25 1998
@@ -12,7 +12,7 @@
 extern inline void init_bh(int nr, void (*routine)(void))
 {
 	bh_base[nr] = routine;
-	bh_mask_count[nr] = 0;
+	atomic_set(&bh_mask_count[nr], 0);
 	bh_mask |= 1 << nr;
 }
 
@@ -97,13 +97,13 @@
 extern inline void disable_bh(int nr)
 {
 	bh_mask &= ~(1 << nr);
-	bh_mask_count[nr]++;
+	atomic_inc(&bh_mask_count[nr]);
 	synchronize_bh();
 }
 
 extern inline void enable_bh(int nr)
 {
-	if (!--bh_mask_count[nr])
+	if (atomic_dec_and_test(&bh_mask_count[nr]))
 		bh_mask |= 1 << nr;
 }
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v2.1.131/linux/include/asm-i386/termios.h	Mon Oct  5 13:13:43 1998
+++ linux/include/asm-i386/termios.h	Wed Dec 16 13:35:49 1998
@@ -50,6 +50,8 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/bvme6000hw.h linux/include/asm-m68k/bvme6000hw.h
--- v2.1.131/linux/include/asm-m68k/bvme6000hw.h	Tue Jun 23 10:01:28 1998
+++ linux/include/asm-m68k/bvme6000hw.h	Thu Dec 17 09:06:25 1998
@@ -98,7 +98,7 @@
 
 #define BVME_CONFIG_REG	0xff500003
 
-#define config_reg_ptr	(unsigned char *)BVME_CONFIG_REG
+#define config_reg_ptr	(volatile unsigned char *)BVME_CONFIG_REG
 
 #define BVME_CONFIG_SW1	0x08
 #define BVME_CONFIG_SW2	0x04
@@ -125,5 +125,25 @@
 #define BVME_IRQ_SCCA_STAT		0x4a
 #define BVME_IRQ_SCCA_RX		0x4c
 #define BVME_IRQ_SCCA_SPCOND		0x4e
+
+/* Address control registers */
+
+#define BVME_ACR_A32VBA		0xff400003
+#define BVME_ACR_A32MSK		0xff410003
+#define BVME_ACR_A24VBA		0xff420003
+#define BVME_ACR_A24MSK		0xff430003
+#define BVME_ACR_A16VBA		0xff440003
+#define BVME_ACR_A32LBA		0xff450003
+#define BVME_ACR_A24LBA		0xff460003
+#define BVME_ACR_ADDRCTL	0xff470003
+
+#define bvme_acr_a32vba		*(volatile unsigned char *)BVME_ACR_A32VBA
+#define bvme_acr_a32msk		*(volatile unsigned char *)BVME_ACR_A32MSK
+#define bvme_acr_a24vba		*(volatile unsigned char *)BVME_ACR_A24VBA
+#define bvme_acr_a24msk		*(volatile unsigned char *)BVME_ACR_A24MSK
+#define bvme_acr_a16vba		*(volatile unsigned char *)BVME_ACR_A16VBA
+#define bvme_acr_a32lba		*(volatile unsigned char *)BVME_ACR_A32LBA
+#define bvme_acr_a24lba		*(volatile unsigned char *)BVME_ACR_A24LBA
+#define bvme_acr_addrctl	*(volatile unsigned char *)BVME_ACR_ADDRCTL
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/ipc.h linux/include/asm-m68k/ipc.h
--- v2.1.131/linux/include/asm-m68k/ipc.h	Fri Nov 22 05:56:36 1996
+++ linux/include/asm-m68k/ipc.h	Thu Dec 17 09:06:25 1998
@@ -23,6 +23,9 @@
 #define SHMGET		23
 #define SHMCTL		24
 
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC		25
+
 #define IPCCALL(version,op)	((version)<<16 | (op))
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h
--- v2.1.131/linux/include/asm-m68k/pgtable.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/pgtable.h	Thu Dec 17 09:06:25 1998
@@ -428,7 +428,7 @@
 #define mk_pte(page, pgprot) \
 ({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)page) + pgprot_val(pgprot); __pte; })
 #define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = virt_to_phys((void *)physpage) + pgprot_val(pgprot); __pte; })
+({ pte_t __pte; pte_val(__pte) = (unsigned long)physpage + pgprot_val(pgprot); __pte; })
 
 extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.1.131/linux/include/asm-m68k/semaphore.h	Mon Jun 16 16:36:00 1997
+++ linux/include/asm-m68k/semaphore.h	Thu Dec 17 09:06:25 1998
@@ -28,6 +28,7 @@
 asmlinkage void __up_wakeup(void /* special register calling convention */);
 
 extern void __down(struct semaphore * sem);
+extern int  __down_interruptible(struct semaphore * sem);
 extern void __up(struct semaphore * sem);
 
 #define sema_init(sem, val)	atomic_set(&((sem)->count), val)
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/spinlock.h linux/include/asm-m68k/spinlock.h
--- v2.1.131/linux/include/asm-m68k/spinlock.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/spinlock.h	Thu Dec 17 09:06:25 1998
@@ -10,10 +10,10 @@
  */
 #if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
 typedef struct { } spinlock_t;
-#define SPIN_LOCK_UNLOCKED { }
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { }
 #else
 typedef struct { int gcc_is_buggy; } spinlock_t;
-#define SPIN_LOCK_UNLOCKED { 0 }
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
 #endif
 
 #define spin_lock_init(lock)	do { } while(0)
@@ -38,9 +38,16 @@
  * can "mix" irq-safe locks - any writer needs to get a
  * irq-safe write-lock, but readers can get non-irqsafe
  * read-locks.
+ *
+ * Gcc-2.7.x has a nasty bug with empty initializers.
  */
+#if (__GNUC__ > 2) || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)
 typedef struct { } rwlock_t;
-#define RW_LOCK_UNLOCKED { }
+#define RW_LOCK_UNLOCKED (rwlock_t) { }
+#else
+typedef struct { int gcc_is_buggy; } rwlock_t;
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
+#endif
 
 #define read_lock(lock)		do { } while(0)
 #define read_unlock(lock)	do { } while(0)
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/string.h linux/include/asm-m68k/string.h
--- v2.1.131/linux/include/asm-m68k/string.h	Fri Dec 20 01:20:03 1996
+++ linux/include/asm-m68k/string.h	Thu Dec 17 09:06:25 1998
@@ -1,7 +1,7 @@
 #ifndef _M68K_STRING_H_
 #define _M68K_STRING_H_
 
-#include <linux/config.h>
+#include <asm/setup.h>
 #include <asm/page.h>
 
 #define __HAVE_ARCH_STRCPY
@@ -315,7 +315,7 @@
   data = c | (c << 8);
   data |= data << 16;
 
-#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060)
+#ifdef CPU_M68040_OR_M68060_ONLY
 
   if (((unsigned long) s) & 0x0f)
 	  memset(s, c, count);
@@ -386,7 +386,7 @@
   unsigned long tmp;
   void *xto = to;
 
-#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060)
+#ifdef CPU_M68040_OR_M68060_ONLY
 
   if (((unsigned long) to | (unsigned long) from) & 0x0f)
 	  return memcpy(to, from, count);
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h
--- v2.1.131/linux/include/asm-m68k/termios.h	Mon Oct  5 13:13:43 1998
+++ linux/include/asm-m68k/termios.h	Wed Dec 16 13:35:49 1998
@@ -58,6 +58,8 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-m68k/uaccess.h linux/include/asm-m68k/uaccess.h
--- v2.1.131/linux/include/asm-m68k/uaccess.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/uaccess.h	Thu Dec 17 09:06:25 1998
@@ -233,7 +233,8 @@
 	 "   .long 5b,8b\n"
 	 ".previous"
 	 : "=a"(to), "=a"(from), "=d"(n), "=&d"(tmp)
-	 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4));
+	 : "r"(n & 3), "0"(to), "1"(from), "2"(n / 4)
+	 : "memory");
     return n;
 }
 
@@ -514,7 +515,7 @@
 	 "13:"						\
 	 : "=a"(to), "=a"(from), "=d"(n)		\
 	 : "0"(to), "1"(from), "2"(n/4)			\
-	 : "d0")
+	 : "d0", "memory")
 
 static inline unsigned long
 __constant_copy_to_user(void *to, const void *from, unsigned long n)
diff -u --recursive --new-file v2.1.131/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.1.131/linux/include/asm-mips/termios.h	Fri Oct 23 22:01:23 1998
+++ linux/include/asm-mips/termios.h	Wed Dec 16 13:35:50 1998
@@ -96,6 +96,8 @@
 #define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-ppc/amigappc.h linux/include/asm-ppc/amigappc.h
--- v2.1.131/linux/include/asm-ppc/amigappc.h	Thu Nov 19 09:56:29 1998
+++ linux/include/asm-ppc/amigappc.h	Mon Dec 21 08:37:24 1998
@@ -16,20 +16,20 @@
 
 #ifndef __ASSEMBLY__
 
-#ifndef iobarrier /* Don't include io.h - avoid circular dependency */
-#define iobarrier() eieio()
+#ifndef iobarrier_rw /* Don't include io.h - avoid circular dependency */
+#define iobarrier_rw() eieio()
 #endif
 
 #define APUS_WRITE(_a_, _v_)				\
 do {							\
 	(*((volatile unsigned char *)(_a_)) = (_v_));	\
-	iobarrier ();					\
+	iobarrier_rw ();				\
 } while (0)
 
 #define APUS_READ(_a_, _v_) 				\
 do {							\
 	(_v_) = (*((volatile unsigned char *)(_a_)));	\
-	iobarrier ();					\
+	iobarrier_rw ();				\
 } while (0)
 #endif /* ndef __ASSEMBLY__ */
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-ppc/io.h linux/include/asm-ppc/io.h
--- v2.1.131/linux/include/asm-ppc/io.h	Thu Nov 19 09:56:29 1998
+++ linux/include/asm-ppc/io.h	Mon Dec 21 08:37:24 1998
@@ -192,7 +192,13 @@
 {
 	__asm__ __volatile__ ("eieio" : : : "memory");
 }
-#define iobarrier() eieio()
+
+/* Enforce in-order execution of data I/O. 
+ * No distinction between read/write on PPC; use eieio for all three.
+ */
+#define iobarrier_rw() eieio()
+#define iobarrier_r()  eieio()
+#define iobarrier_w()  eieio()
 
 /*
  * 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
diff -u --recursive --new-file v2.1.131/linux/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
--- v2.1.131/linux/include/asm-ppc/mmu_context.h	Mon Oct  5 13:13:43 1998
+++ linux/include/asm-ppc/mmu_context.h	Mon Dec 21 08:37:24 1998
@@ -38,7 +38,7 @@
 #define MUNGE_CONTEXT(n)        (((n) * 897) & LAST_CONTEXT)
 #endif
 
-extern int next_mmu_context;
+extern atomic_t next_mmu_context;
 extern void mmu_context_overflow(void);
 
 #ifndef CONFIG_8xx
@@ -54,9 +54,9 @@
 do { 								\
 	struct mm_struct *mm = (tsk)->mm;			\
 	if (mm->context == NO_CONTEXT) {			\
-		if (next_mmu_context == LAST_CONTEXT)		\
+		if (atomic_read(&next_mmu_context) == LAST_CONTEXT)		\
 			mmu_context_overflow();			\
-		mm->context = MUNGE_CONTEXT(++next_mmu_context);\
+		mm->context = MUNGE_CONTEXT(atomic_inc_return(&next_mmu_context));\
 	}							\
 } while (0)
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-ppc/resource.h linux/include/asm-ppc/resource.h
--- v2.1.131/linux/include/asm-ppc/resource.h	Sat Aug 16 09:51:09 1997
+++ linux/include/asm-ppc/resource.h	Mon Dec 21 08:37:24 1998
@@ -21,7 +21,7 @@
     {LONG_MAX, LONG_MAX},			/* RLIMIT_CPU */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_FSIZE */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_DATA */	\
-    {_STK_LIM, _STK_LIM},			/* RLIMIT_STACK */	\
+    {_STK_LIM, LONG_MAX},			/* RLIMIT_STACK */	\
     {       0, LONG_MAX},			/* RLIMIT_CORE */	\
     {LONG_MAX, LONG_MAX},			/* RLIMIT_RSS */	\
     {MAX_TASKS_PER_USER, MAX_TASKS_PER_USER},	/* RLIMIT_NPROC */	\
diff -u --recursive --new-file v2.1.131/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.1.131/linux/include/asm-sparc/termios.h	Mon Oct  5 13:13:43 1998
+++ linux/include/asm-sparc/termios.h	Wed Dec 16 13:35:50 1998
@@ -66,6 +66,8 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.131/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.1.131/linux/include/asm-sparc64/termios.h	Mon Oct  5 13:13:44 1998
+++ linux/include/asm-sparc64/termios.h	Wed Dec 16 13:35:50 1998
@@ -66,6 +66,8 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
 
diff -u --recursive --new-file v2.1.131/linux/include/linux/awe_voice.h linux/include/linux/awe_voice.h
--- v2.1.131/linux/include/linux/awe_voice.h	Sat Nov 29 10:33:21 1997
+++ linux/include/linux/awe_voice.h	Wed Dec 16 12:52:01 1998
@@ -2,10 +2,10 @@
  * sound/awe_voice.h
  *
  * Voice information definitions for the low level driver for the 
- * AWE32/Sound Blaster 32 wave table synth.
- *   version 0.4.2c; Oct. 7, 1997
+ * AWE32/SB32/AWE64 wave table synth.
+ *   version 0.4.3; Mar. 1, 1998
  *
- * Copyright (C) 1996,1997 Takashi Iwai
+ * Copyright (C) 1996-1998 Takashi Iwai
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -55,6 +55,8 @@
 #define AWE_UNLOAD_PATCH	4	/* none */
 #define AWE_REPLACE_DATA	5	/* awe_sample_info (optarg=#channels)*/
 #define AWE_MAP_PRESET		6	/* awe_voice_map */
+/*#define AWE_PROBE_INFO	7*/	/* awe_voice_map (pat only) */
+#define AWE_PROBE_DATA		8	/* optarg=sample */
 #define AWE_LOAD_CHORUS_FX	0x10	/* awe_chorus_fx_rec (optarg=mode) */
 #define AWE_LOAD_REVERB_FX	0x11	/* awe_reverb_fx_rec (optarg=mode) */
 
@@ -88,6 +90,7 @@
 #define AWE_PAT_TYPE_MAP	7
 
 #define AWE_PAT_LOCKED		0x100	/* lock the samples */
+#define AWE_PAT_SHARED		0x200	/* sample is shared */
 
 	short reserved;
 	char name[AWE_PATCH_NAME_LEN];
@@ -126,6 +129,30 @@
 	unsigned short reserved[4];	/* not used */
 } awe_voice_parm;
 
+typedef struct _awe_voice_parm_block {
+	unsigned short moddelay;	/* modulation delay (0x8000) */
+	unsigned char modatk, modhld;
+	unsigned char moddcy, modsus;
+	unsigned short modrel, moddummy;
+	short modkeyhold, modkeydecay;	/* envelope change per key (not used) */
+	unsigned short voldelay;	/* volume delay (0x8000) */
+	unsigned char volatk, volhld;
+	unsigned char voldcy, volsus;
+	unsigned char volrel, voldummy;
+	short volkeyhold, volkeydecay;	/* envelope change per key (not used) */
+	unsigned short lfo1delay;	/* LFO1 delay (0x8000) */
+	unsigned short lfo2delay;	/* LFO2 delay (0x8000) */
+	unsigned char env1fc, env1pit;
+	unsigned char lfo1fc, lfo1pit;
+	unsigned char lfo1freq, lfo1vol;
+	unsigned char lfo2freq, lfo2pit;
+	unsigned char cutoff;		/* initial cutoff (0xff) */
+	unsigned char filterQ;		/* initial filter Q [0-15] (0x0) */
+	unsigned char chorus;		/* chorus send (0x00) */
+	unsigned char reverb;		/* reverb send (0x00) */
+	unsigned short reserved[4];	/* not used */
+} awe_voice_parm_block;
+
 #define AWE_VOICE_PARM_SIZE	48
 
 
@@ -419,7 +446,7 @@
 /* 0*/	AWE_MD_EXCLUSIVE_OFF,	/* obsolete */
 /* 1*/	AWE_MD_EXCLUSIVE_ON,	/* obsolete */
 /* 2*/	AWE_MD_VERSION,		/* read only */
-/* 3*/	AWE_MD_EXCLUSIVE_SOUND,	/* ignored */
+/* 3*/	AWE_MD_EXCLUSIVE_SOUND,	/* 0/1: exclusive note on (default=1) */
 /* 4*/	AWE_MD_REALTIME_PAN,	/* 0/1: do realtime pan change (default=1) */
 /* 5*/	AWE_MD_GUS_BANK,	/* bank number for GUS patches (default=0) */
 /* 6*/	AWE_MD_KEEP_EFFECT,	/* 0/1: keep effect values, (default=0) */
@@ -430,6 +457,13 @@
 /*11*/	AWE_MD_DEF_BANK,	/* integer: default bank number (def=0) */
 /*12*/	AWE_MD_DEF_DRUM,	/* integer: default drumset number (def=0) */
 /*13*/	AWE_MD_TOGGLE_DRUM_BANK, /* 0/1: toggle drum flag with bank# (def=0) */
+/*14*/	AWE_MD_NEW_VOLUME_CALC,	/* 0/1: volume calculation mode (def=1) */
+/*15*/	AWE_MD_CHORUS_MODE,	/* integer: chorus mode (def=2) */
+/*16*/	AWE_MD_REVERB_MODE,	/* integer: chorus mode (def=4) */
+/*17*/	AWE_MD_BASS_LEVEL,	/* integer: bass level (def=5) */
+/*18*/	AWE_MD_TREBLE_LEVEL,	/* integer: treble level (def=9) */
+/*19*/	AWE_MD_DEBUG_MODE,	/* integer: debug level (def=0) */
+/*20*/	AWE_MD_PAN_EXCHANGE,	/* 0/1: exchange panning direction (def=0) */
 	AWE_MD_END,
 };
 
diff -u --recursive --new-file v2.1.131/linux/include/linux/coda.h linux/include/linux/coda.h
--- v2.1.131/linux/include/linux/coda.h	Sat Sep  5 16:46:41 1998
+++ linux/include/linux/coda.h	Mon Dec 21 14:23:28 1998
@@ -5,8 +5,8 @@
  * Linux modifications by Peter Braam, Aug 1996
  */
 
-#ifndef _CFS_HEADER_
-#define _CFS_HEADER_
+#ifndef _CODA_HEADER_
+#define _CODA_HEADER_
 
 
 
@@ -15,7 +15,11 @@
 #include <sys/types.h>
 #endif 
 
-#ifdef DJGPP
+#ifndef CODA_MAXSYMLINKS
+#define CODA_MAXSYMLINKS 10
+#endif
+
+#if defined(DJGPP) || defined(__CYGWIN32__)
 #ifdef KERNEL
 typedef unsigned long u_long;
 typedef unsigned int u_int;
@@ -23,7 +27,11 @@
 typedef u_long ino_t;
 typedef u_long dev_t;
 typedef void * caddr_t;
-typedef u_long u_quad_t;
+#ifdef DOS
+typedef unsigned __int64 u_quad_t;
+#else 
+typedef unsigned long long u_quad_t;
+#endif
 
 #define inline
 
@@ -34,12 +42,12 @@
 #else  /* DJGPP but not KERNEL */
 #include <sys/types.h>
 #include <sys/time.h>
-typedef u_long u_quad_t;
+typedef unsigned long long u_quad_t;
 #endif /* !KERNEL */
 #endif /* !DJGPP */
 
 
-#if defined(__linux__) || defined(__CYGWIN32__)
+#if defined(__linux__)
 #define cdev_t u_quad_t
 #if !defined(_UQUAD_T_) && (!defined(__GLIBC__) || __GLIBC__ < 2)
 #define _UQUAD_T_ 1
@@ -61,9 +69,9 @@
 /*
  * Cfs constants
  */
-#define CFS_MAXNAMLEN   255
-#define CFS_MAXPATHLEN  1024
-#define CFS_MAXSYMLINK  10
+#define CODA_MAXNAMLEN   255
+#define CODA_MAXPATHLEN  1024
+#define CODA_MAXSYMLINK  10
 
 /* these are Coda's version of O_RDONLY etc combinations
  * to deal with VFS open modes
@@ -79,9 +87,9 @@
 #define C_M_WRITE 00200
 
 /* for access Venus will use */
+#define C_A_C_OK    8               /* Test for writing upon create.  */
 #define C_A_R_OK    4               /* Test for read permission.  */
 #define C_A_W_OK    2               /* Test for write permission.  */
-#define C_A_C_OK    8               /* Test for writing upon create.  */
 #define C_A_X_OK    1               /* Test for execute permission.  */
 #define C_A_F_OK    0               /* Test for existence.  */
 
@@ -94,23 +102,23 @@
         unsigned short	d_reclen;		/* length of this record */
         char 		d_type;			/* file type, see below */
         char		d_namlen;		/* length of string in d_name */
-        char		d_name[CFS_MAXNAMLEN + 1];/* name must be no longer than this */
+        char		d_name[CODA_MAXNAMLEN + 1];/* name must be no longer than this */
 };
 #undef DIRSIZ
-#define DIRSIZ(dp)      ((sizeof (struct venus_dirent) - (CFS_MAXNAMLEN+1)) + \
+#define DIRSIZ(dp)      ((sizeof (struct venus_dirent) - (CODA_MAXNAMLEN+1)) + \
                          (((dp)->d_namlen+1 + 3) &~ 3))
 
 /*
  * File types
  */
 #define	CDT_UNKNOWN	 0
-#define	CDT_FIFO		 1
+#define	CDT_FIFO	 1
 #define	CDT_CHR		 2
 #define	CDT_DIR		 4
 #define	CDT_BLK		 6
 #define	CDT_REG		 8
 #define	CDT_LNK		10
-#define	CDT_SOCK		12
+#define	CDT_SOCK	12
 #define	CDT_WHT		14
 
 /*
@@ -138,14 +146,27 @@
 } ViceFid;
 #endif	/* VICEFID */
 
-static inline ino_t coda_f2i(struct ViceFid *fid)
+
+#ifdef __linux__
+static __inline__ ino_t  coda_f2i(struct ViceFid *fid)
 {
-      if ( fid ) {
-              return (fid->Unique + (fid->Vnode << 10) + (fid->Volume << 20));
-      } else { 
-              return 0;
-      }
+	if ( ! fid ) 
+		return 0; 
+	if (fid->Vnode == 0xfffffffe || fid->Vnode == 0xffffffff)
+		return ((fid->Volume << 20) | (fid->Unique & 0xfffff));
+	else
+		return (fid->Unique + (fid->Vnode<<10) + (fid->Volume<<20));
 }
+	
+#else
+#define coda_f2i(fid)\
+	((fid) ? ((fid)->Unique + ((fid)->Vnode<<10) + ((fid)->Volume<<20)) : 0)
+#endif
+
+
+#ifndef __BIT_TYPES_DEFINED__
+#define u_int32_t unsigned int
+#endif
 
 
 #ifndef _VUID_T_
@@ -158,11 +179,7 @@
 #define _CODACRED_T_
 struct coda_cred {
     vuid_t cr_uid, cr_euid, cr_suid, cr_fsuid; /* Real, efftve, set, fs uid*/
-#if	defined(__NetBSD__) || defined(__FreeBSD__)
-    vgid_t cr_groupid, cr_egid, cr_sgid, cr_fsgid; /* same for groups */
-#else
-    vgid_t cr_gid,     cr_egid, cr_sgid, cr_fsgid; /* same for groups */
-#endif
+    vgid_t cr_groupid,     cr_egid, cr_sgid, cr_fsgid; /* same for groups */
 };
 #endif 
 
@@ -174,7 +191,7 @@
 enum coda_vtype	{ C_VNON, C_VREG, C_VDIR, C_VBLK, C_VCHR, C_VLNK, C_VSOCK, C_VFIFO, C_VBAD };
 
 struct coda_vattr {
-	enum coda_vtype	va_type;	/* vnode type (for create) */
+	int     	va_type;	/* vnode type (for create) */
 	u_short		va_mode;	/* files access mode and type */
 	short		va_nlink;	/* number of references to file */
 	vuid_t		va_uid;		/* owner user id */
@@ -198,50 +215,59 @@
  * Kernel <--> Venus communications.
  */
 
-#define CFS_ROOT	((u_long) 2)
-#define CFS_SYNC	((u_long) 3)
-#define CFS_OPEN	((u_long) 4)
-#define CFS_CLOSE	((u_long) 5)
-#define CFS_IOCTL	((u_long) 6)
-#define CFS_GETATTR	((u_long) 7)
-#define CFS_SETATTR	((u_long) 8)
-#define CFS_ACCESS	((u_long) 9)
-#define CFS_LOOKUP	((u_long) 10)
-#define CFS_CREATE	((u_long) 11)
-#define CFS_REMOVE	((u_long) 12)
-#define CFS_LINK	((u_long) 13)
-#define CFS_RENAME	((u_long) 14)
-#define CFS_MKDIR	((u_long) 15)
-#define CFS_RMDIR	((u_long) 16)
-#define CFS_READDIR	((u_long) 17)
-#define CFS_SYMLINK	((u_long) 18)
-#define CFS_READLINK	((u_long) 19)
-#define CFS_FSYNC	((u_long) 20)
-#define CFS_INACTIVE	((u_long) 21)
-#define CFS_VGET	((u_long) 22)
-#define CFS_SIGNAL	((u_long) 23)
-#define CFS_REPLACE	((u_long) 24)
-#define CFS_FLUSH       ((u_long) 25)
-#define CFS_PURGEUSER   ((u_long) 26)
-#define CFS_ZAPFILE     ((u_long) 27)
-#define CFS_ZAPDIR      ((u_long) 28)
-/* #define CFS_ZAPVNODE    ((u_long) 29)   obsolete */ 
-#define CFS_PURGEFID    ((u_long) 30)
-#define CFS_OPEN_BY_PATH ((u_long) 31)
-#define CFS_NCALLS 32
+#define CODA_ROOT	2
+#define CODA_SYNC	3
+#define CODA_OPEN	4
+#define CODA_CLOSE	5
+#define CODA_IOCTL	6
+#define CODA_GETATTR	7
+#define CODA_SETATTR	8
+#define CODA_ACCESS	9
+#define CODA_LOOKUP	10
+#define CODA_CREATE	11
+#define CODA_REMOVE	12
+#define CODA_LINK	13
+#define CODA_RENAME	14
+#define CODA_MKDIR	15
+#define CODA_RMDIR	16
+#define CODA_READDIR	17
+#define CODA_SYMLINK	18
+#define CODA_READLINK	19
+#define CODA_FSYNC	20
+#define CODA_INACTIVE	21
+#define CODA_VGET	22
+#define CODA_SIGNAL	23
+#define CODA_REPLACE	24
+#define CODA_FLUSH       25
+#define CODA_PURGEUSER   26
+#define CODA_ZAPFILE     27
+#define CODA_ZAPDIR      28
+#define CODA_PURGEFID    30
+#define CODA_OPEN_BY_PATH 31
+#define CODA_RESOLVE     32
+#define CODA_REINTEGRATE 33
+#define CODA_NCALLS 34
 
-#define DOWNCALL(opcode) (opcode >= CFS_REPLACE && opcode <= CFS_PURGEFID)
+#define DOWNCALL(opcode) (opcode >= CODA_REPLACE && opcode <= CODA_PURGEFID)
 
 #define VC_MAXDATASIZE	    8192
 #define VC_MAXMSGSIZE      sizeof(union inputArgs)+sizeof(union outputArgs) +\
                             VC_MAXDATASIZE  
 
-
+#define CIOC_KERNEL_VERSION _IOWR('c', 10, sizeof (int))
+#if	0
+	/* don't care about kernel version number */
+#define CODA_KERNEL_VERSION 0
+	/* The old venus 4.6 compatible interface */
+#define CODA_KERNEL_VERSION 1
+#endif
+	/* venus_lookup gets an extra parameter to aid windows.*/
+#define CODA_KERNEL_VERSION 2
 
 /*
  *        Venus <-> Coda  RPC arguments
  */
-struct cfs_in_hdr {
+struct coda_in_hdr {
     unsigned long opcode;
     unsigned long unique;	    /* Keep multiple outstanding msgs distinct */
     u_short pid;		    /* Common to all */
@@ -251,53 +277,53 @@
 };
 
 /* Really important that opcode and unique are 1st two fields! */
-struct cfs_out_hdr {
+struct coda_out_hdr {
     unsigned long opcode;
     unsigned long unique;	
     unsigned long result;
 };
 
-/* cfs_root: NO_IN */
-struct cfs_root_out {
-    struct cfs_out_hdr oh;
+/* coda_root: NO_IN */
+struct coda_root_out {
+    struct coda_out_hdr oh;
     ViceFid VFid;
 };
 
-struct cfs_root_in {
-    struct cfs_in_hdr in;
+struct coda_root_in {
+    struct coda_in_hdr in;
 };
 
-/* cfs_sync: */
-/* Nothing needed for cfs_sync */
+/* coda_sync: */
+/* Nothing needed for coda_sync */
 
-/* cfs_open: */
-struct cfs_open_in {
-    struct cfs_in_hdr ih;
+/* coda_open: */
+struct coda_open_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int	flags;
 };
 
-struct cfs_open_out {
-    struct cfs_out_hdr oh;
+struct coda_open_out {
+    struct coda_out_hdr oh;
     cdev_t	dev;
     ino_t	inode;
 };
 
 
-/* cfs_close: */
-struct cfs_close_in {
-    struct cfs_in_hdr ih;
+/* coda_close: */
+struct coda_close_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int	flags;
 };
 
-struct cfs_close_out {
-    struct cfs_out_hdr out;
+struct coda_close_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_ioctl: */
-struct cfs_ioctl_in {
-    struct cfs_in_hdr ih;
+/* coda_ioctl: */
+struct coda_ioctl_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
     int	cmd;
     int	len;
@@ -305,64 +331,70 @@
     char *data;			/* Place holder for data. */
 };
 
-struct cfs_ioctl_out {
-    struct cfs_out_hdr oh;
+struct coda_ioctl_out {
+    struct coda_out_hdr oh;
     int	len;
     caddr_t	data;		/* Place holder for data. */
 };
 
 
-/* cfs_getattr: */
-struct cfs_getattr_in {
-    struct cfs_in_hdr ih;
+/* coda_getattr: */
+struct coda_getattr_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
 };
 
-struct cfs_getattr_out {
-    struct cfs_out_hdr oh;
+struct coda_getattr_out {
+    struct coda_out_hdr oh;
     struct coda_vattr attr;
 };
 
 
-/* cfs_setattr: NO_OUT */
-struct cfs_setattr_in {
-    struct cfs_in_hdr ih;
+/* coda_setattr: NO_OUT */
+struct coda_setattr_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
     struct coda_vattr attr;
 };
 
-struct cfs_setattr_out {
-    struct cfs_out_hdr out;
+struct coda_setattr_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_access: NO_OUT */
-struct cfs_access_in {
-    struct cfs_in_hdr ih;
+/* coda_access: NO_OUT */
+struct coda_access_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int	flags;
 };
 
-struct cfs_access_out {
-    struct cfs_out_hdr out;
+struct coda_access_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_lookup: */
-struct  cfs_lookup_in {
-    struct cfs_in_hdr ih;
+
+/* lookup flags */
+#define CLU_CASE_SENSITIVE     0x01
+#define CLU_CASE_INSENSITIVE   0x02
+
+/* coda_lookup: */
+struct  coda_lookup_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int         name;		/* Place holder for data. */
+    int         flags;	
 };
 
-struct cfs_lookup_out {
-    struct cfs_out_hdr oh;
+struct coda_lookup_out {
+    struct coda_out_hdr oh;
     ViceFid VFid;
     int	vtype;
 };
 
 
-/* cfs_create: */
-struct cfs_create_in {
-    struct cfs_in_hdr ih;
+/* coda_create: */
+struct coda_create_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
     struct coda_vattr attr;
     int excl;
@@ -370,188 +402,188 @@
     int 	name;		/* Place holder for data. */
 };
 
-struct cfs_create_out {
-    struct cfs_out_hdr oh;
+struct coda_create_out {
+    struct coda_out_hdr oh;
     ViceFid VFid;
     struct coda_vattr attr;
 };
 
 
-/* cfs_remove: NO_OUT */
-struct cfs_remove_in {
-    struct cfs_in_hdr ih;
+/* coda_remove: NO_OUT */
+struct coda_remove_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int name;		/* Place holder for data. */
 };
 
-struct cfs_remove_out {
-    struct cfs_out_hdr out;
+struct coda_remove_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_link: NO_OUT */
-struct cfs_link_in {
-    struct cfs_in_hdr ih;
+/* coda_link: NO_OUT */
+struct coda_link_in {
+    struct coda_in_hdr ih;
     ViceFid sourceFid;          /* cnode to link *to* */
     ViceFid destFid;            /* Directory in which to place link */
     int tname;		/* Place holder for data. */
 };
 
-struct cfs_link_out {
-    struct cfs_out_hdr out;
+struct coda_link_out {
+    struct coda_out_hdr out;
 };
 
 
-/* cfs_rename: NO_OUT */
-struct cfs_rename_in {
-    struct cfs_in_hdr ih;
+/* coda_rename: NO_OUT */
+struct coda_rename_in {
+    struct coda_in_hdr ih;
     ViceFid	sourceFid;
     int 	srcname;
     ViceFid destFid;
     int 	destname;
 };
 
-struct cfs_rename_out {
-    struct cfs_out_hdr out;
+struct coda_rename_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_mkdir: */
-struct cfs_mkdir_in {
-    struct cfs_in_hdr ih;
+/* coda_mkdir: */
+struct coda_mkdir_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     struct coda_vattr attr;
     int	   name;		/* Place holder for data. */
 };
 
-struct cfs_mkdir_out {
-    struct cfs_out_hdr oh;
+struct coda_mkdir_out {
+    struct coda_out_hdr oh;
     ViceFid VFid;
     struct coda_vattr attr;
 };
 
 
-/* cfs_rmdir: NO_OUT */
-struct cfs_rmdir_in {
-    struct cfs_in_hdr ih;
+/* coda_rmdir: NO_OUT */
+struct coda_rmdir_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int name;		/* Place holder for data. */
 };
 
-struct cfs_rmdir_out {
-    struct cfs_out_hdr out;
+struct coda_rmdir_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_readdir: */
-struct cfs_readdir_in {
-    struct cfs_in_hdr ih;
+/* coda_readdir: */
+struct coda_readdir_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int	count;
     int	offset;
 };
 
-struct cfs_readdir_out {
-    struct cfs_out_hdr oh;
+struct coda_readdir_out {
+    struct coda_out_hdr oh;
     int	size;
     caddr_t	data;		/* Place holder for data. */
 };
 
-/* cfs_symlink: NO_OUT */
-struct cfs_symlink_in {
-    struct cfs_in_hdr ih;
+/* coda_symlink: NO_OUT */
+struct coda_symlink_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;          /* Directory to put symlink in */
     int srcname;
     struct coda_vattr attr;
     int tname;
 };
 
-struct cfs_symlink_out {
-    struct cfs_out_hdr out;
+struct coda_symlink_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_readlink: */
-struct cfs_readlink_in {
-    struct cfs_in_hdr ih;
+/* coda_readlink: */
+struct coda_readlink_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
 };
 
-struct cfs_readlink_out {
-    struct cfs_out_hdr oh;
+struct coda_readlink_out {
+    struct coda_out_hdr oh;
     int	count;
     caddr_t	data;		/* Place holder for data. */
 };
 
 
-/* cfs_fsync: NO_OUT */
-struct cfs_fsync_in {
-    struct cfs_in_hdr ih;
+/* coda_fsync: NO_OUT */
+struct coda_fsync_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
 };
 
-struct cfs_fsync_out {
-    struct cfs_out_hdr out;
+struct coda_fsync_out {
+    struct coda_out_hdr out;
 };
 
-/* cfs_inactive: NO_OUT */
-struct cfs_inactive_in {
-    struct cfs_in_hdr ih;
+/* coda_inactive: NO_OUT */
+struct coda_inactive_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
 };
 
-/* cfs_vget: */
-struct cfs_vget_in {
-    struct cfs_in_hdr ih;
+/* coda_vget: */
+struct coda_vget_in {
+    struct coda_in_hdr ih;
     ViceFid VFid;
 };
 
-struct cfs_vget_out {
-    struct cfs_out_hdr oh;
+struct coda_vget_out {
+    struct coda_out_hdr oh;
     ViceFid VFid;
     int	vtype;
 };
 
 
-/* CFS_SIGNAL is out-of-band, doesn't need data. */
-/* CFS_INVALIDATE is a venus->kernel call */
-/* CFS_FLUSH is a venus->kernel call */
-
-/* cfs_purgeuser: */
-/* CFS_PURGEUSER is a venus->kernel call */
-struct cfs_purgeuser_out {
-    struct cfs_out_hdr oh;
+/* CODA_SIGNAL is out-of-band, doesn't need data. */
+/* CODA_INVALIDATE is a venus->kernel call */
+/* CODA_FLUSH is a venus->kernel call */
+
+/* coda_purgeuser: */
+/* CODA_PURGEUSER is a venus->kernel call */
+struct coda_purgeuser_out {
+    struct coda_out_hdr oh;
     struct coda_cred cred;
 };
 
-/* cfs_zapfile: */
-/* CFS_ZAPFILE is a venus->kernel call */
-struct cfs_zapfile_out {  
-    struct cfs_out_hdr oh;
+/* coda_zapfile: */
+/* CODA_ZAPFILE is a venus->kernel call */
+struct coda_zapfile_out {  
+    struct coda_out_hdr oh;
     ViceFid CodaFid;
 };
 
-/* cfs_zapdir: */
-/* CFS_ZAPDIR is a venus->kernel call */	
-struct cfs_zapdir_out {	  
-    struct cfs_out_hdr oh;
+/* coda_zapdir: */
+/* CODA_ZAPDIR is a venus->kernel call */	
+struct coda_zapdir_out {	  
+    struct coda_out_hdr oh;
     ViceFid CodaFid;
 };
 
-/* cfs_zapnode: */
-/* CFS_ZAPVNODE is a venus->kernel call */	
-struct cfs_zapvnode_out { 
-    struct cfs_out_hdr oh;
+/* coda_zapnode: */
+/* CODA_ZAPVNODE is a venus->kernel call */	
+struct coda_zapvnode_out { 
+    struct coda_out_hdr oh;
     struct coda_cred cred;
     ViceFid VFid;
 };
 
-/* cfs_purgefid: */
-/* CFS_PURGEFID is a venus->kernel call */	
-struct cfs_purgefid_out { 
-    struct cfs_out_hdr oh;
+/* coda_purgefid: */
+/* CODA_PURGEFID is a venus->kernel call */	
+struct coda_purgefid_out { 
+    struct coda_out_hdr oh;
     ViceFid CodaFid;
 };
 
-/* cfs_rdwr: */
-struct cfs_rdwr_in {
-    struct cfs_in_hdr ih;
+/* coda_rdwr: */
+struct coda_rdwr_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int	rwflag;
     int	count;
@@ -560,97 +592,97 @@
     caddr_t	data;		/* Place holder for data. */	
 };
 
-struct cfs_rdwr_out {
-    struct cfs_out_hdr oh;
+struct coda_rdwr_out {
+    struct coda_out_hdr oh;
     int	rwflag;
     int	count;
     caddr_t	data;	/* Place holder for data. */
 };
 
 
-/* cfs_replace: */
-/* CFS_REPLACE is a venus->kernel call */	
-struct cfs_replace_out { /* cfs_replace is a venus->kernel call */
-    struct cfs_out_hdr oh;
+/* coda_replace: */
+/* CODA_REPLACE is a venus->kernel call */	
+struct coda_replace_out { /* coda_replace is a venus->kernel call */
+    struct coda_out_hdr oh;
     ViceFid NewFid;
     ViceFid OldFid;
 };
 
-/* cfs_open_by_path: */
-struct cfs_open_by_path_in {
-    struct cfs_in_hdr ih;
+/* coda_open_by_path: */
+struct coda_open_by_path_in {
+    struct coda_in_hdr ih;
     ViceFid	VFid;
     int	flags;
 };
 
-struct cfs_open_by_path_out {
-    struct cfs_out_hdr oh;
+struct coda_open_by_path_out {
+    struct coda_out_hdr oh;
 	int path;
 };
 
 /* 
- * Occasionally, we don't cache the fid returned by CFS_LOOKUP. 
+ * Occasionally, we don't cache the fid returned by CODA_LOOKUP. 
  * For instance, if the fid is inconsistent. 
  * This case is handled by setting the top bit of the type result parameter.
  */
-#define CFS_NOCACHE          0x80000000
+#define CODA_NOCACHE          0x80000000
 
 union inputArgs {
-    struct cfs_in_hdr ih;		/* NB: every struct below begins with an ih */
-    struct cfs_open_in cfs_open;
-    struct cfs_close_in cfs_close;
-    struct cfs_ioctl_in cfs_ioctl;
-    struct cfs_getattr_in cfs_getattr;
-    struct cfs_setattr_in cfs_setattr;
-    struct cfs_access_in cfs_access;
-    struct cfs_lookup_in cfs_lookup;
-    struct cfs_create_in cfs_create;
-    struct cfs_remove_in cfs_remove;
-    struct cfs_link_in cfs_link;
-    struct cfs_rename_in cfs_rename;
-    struct cfs_mkdir_in cfs_mkdir;
-    struct cfs_rmdir_in cfs_rmdir;
-    struct cfs_readdir_in cfs_readdir;
-    struct cfs_symlink_in cfs_symlink;
-    struct cfs_readlink_in cfs_readlink;
-    struct cfs_fsync_in cfs_fsync;
-    struct cfs_inactive_in cfs_inactive;
-    struct cfs_vget_in cfs_vget;
-    struct cfs_rdwr_in cfs_rdwr;
-	struct cfs_open_by_path_in cfs_open_by_path;
+    struct coda_in_hdr ih;		/* NB: every struct below begins with an ih */
+    struct coda_open_in coda_open;
+    struct coda_close_in coda_close;
+    struct coda_ioctl_in coda_ioctl;
+    struct coda_getattr_in coda_getattr;
+    struct coda_setattr_in coda_setattr;
+    struct coda_access_in coda_access;
+    struct coda_lookup_in coda_lookup;
+    struct coda_create_in coda_create;
+    struct coda_remove_in coda_remove;
+    struct coda_link_in coda_link;
+    struct coda_rename_in coda_rename;
+    struct coda_mkdir_in coda_mkdir;
+    struct coda_rmdir_in coda_rmdir;
+    struct coda_readdir_in coda_readdir;
+    struct coda_symlink_in coda_symlink;
+    struct coda_readlink_in coda_readlink;
+    struct coda_fsync_in coda_fsync;
+    struct coda_inactive_in coda_inactive;
+    struct coda_vget_in coda_vget;
+    struct coda_rdwr_in coda_rdwr;
+	struct coda_open_by_path_in coda_open_by_path;
 };
 
 union outputArgs {
-    struct cfs_out_hdr oh;		/* NB: every struct below begins with an oh */
-    struct cfs_root_out cfs_root;
-    struct cfs_open_out cfs_open;
-    struct cfs_ioctl_out cfs_ioctl;
-    struct cfs_getattr_out cfs_getattr;
-    struct cfs_lookup_out cfs_lookup;
-    struct cfs_create_out cfs_create;
-    struct cfs_mkdir_out cfs_mkdir;
-    struct cfs_readdir_out cfs_readdir;
-    struct cfs_readlink_out cfs_readlink;
-    struct cfs_vget_out cfs_vget;
-    struct cfs_purgeuser_out cfs_purgeuser;
-    struct cfs_zapfile_out cfs_zapfile;
-    struct cfs_zapdir_out cfs_zapdir;
-    struct cfs_zapvnode_out cfs_zapvnode;
-    struct cfs_purgefid_out cfs_purgefid;
-    struct cfs_rdwr_out cfs_rdwr;
-    struct cfs_replace_out cfs_replace;
-	struct cfs_open_by_path_out cfs_open_by_path;
+    struct coda_out_hdr oh;		/* NB: every struct below begins with an oh */
+    struct coda_root_out coda_root;
+    struct coda_open_out coda_open;
+    struct coda_ioctl_out coda_ioctl;
+    struct coda_getattr_out coda_getattr;
+    struct coda_lookup_out coda_lookup;
+    struct coda_create_out coda_create;
+    struct coda_mkdir_out coda_mkdir;
+    struct coda_readdir_out coda_readdir;
+    struct coda_readlink_out coda_readlink;
+    struct coda_vget_out coda_vget;
+    struct coda_purgeuser_out coda_purgeuser;
+    struct coda_zapfile_out coda_zapfile;
+    struct coda_zapdir_out coda_zapdir;
+    struct coda_zapvnode_out coda_zapvnode;
+    struct coda_purgefid_out coda_purgefid;
+    struct coda_rdwr_out coda_rdwr;
+    struct coda_replace_out coda_replace;
+	struct coda_open_by_path_out coda_open_by_path;
 };    
 
-union cfs_downcalls {
-    /* CFS_INVALIDATE is a venus->kernel call */
-    /* CFS_FLUSH is a venus->kernel call */
-    struct cfs_purgeuser_out purgeuser;
-    struct cfs_zapfile_out zapfile;
-    struct cfs_zapdir_out zapdir;
-    struct cfs_zapvnode_out zapvnode;
-    struct cfs_purgefid_out purgefid;
-    struct cfs_replace_out replace;
+union coda_downcalls {
+    /* CODA_INVALIDATE is a venus->kernel call */
+    /* CODA_FLUSH is a venus->kernel call */
+    struct coda_purgeuser_out purgeuser;
+    struct coda_zapfile_out zapfile;
+    struct coda_zapdir_out zapdir;
+    struct coda_zapvnode_out zapvnode;
+    struct coda_purgefid_out purgefid;
+    struct coda_replace_out replace;
 };
 
 
@@ -665,14 +697,23 @@
         short out_size;         /* Maximum size of output buffer, <= 2K */
 };
 
+#if defined(__CYGWIN32__) || defined(DJGPP)
 struct PioctlData {
+	unsigned long cmd;
         const char *path;
         int follow;
         struct ViceIoctl vi;
 };
+#else
+struct PioctlData {
+        const char *path;
+        int follow;
+        struct ViceIoctl vi;
+};
+#endif
 
-#define	CFS_CONTROL		".CONTROL"
-#define CFS_CONTROLLEN           8
+#define	CODA_CONTROL		".CONTROL"
+#define CODA_CONTROLLEN           8
 #define	CTL_VOL			-1
 #define	CTL_VNO			-1
 #define	CTL_UNI			-1
diff -u --recursive --new-file v2.1.131/linux/include/linux/coda_cache.h linux/include/linux/coda_cache.h
--- v2.1.131/linux/include/linux/coda_cache.h	Tue Mar 17 22:18:15 1998
+++ linux/include/linux/coda_cache.h	Fri Dec 18 12:45:00 1998
@@ -30,7 +30,7 @@
 
 /* for downcalls and attributes and lookups */
 void coda_flag_inode(struct inode *inode, int flag);
-void coda_flag_alias_children(struct inode *inode, int flag);
+void coda_flag_inode_children(struct inode *inode, int flag);
 
 
 /*
diff -u --recursive --new-file v2.1.131/linux/include/linux/coda_fs_i.h linux/include/linux/coda_fs_i.h
--- v2.1.131/linux/include/linux/coda_fs_i.h	Sat Sep  5 16:46:41 1998
+++ linux/include/linux/coda_fs_i.h	Mon Dec 21 14:27:32 1998
@@ -33,12 +33,12 @@
 };
 
 /* flags */
-#define C_VATTR       0x1         /* Validity of vattr in the cnode */
-#define C_SYMLINK     0x2         /* Validity of symlink pointer in the cnode */
-#define C_DYING       0x4	  /* Set for outstanding cnodes from venus (which died) */
-#define C_PURGE      0x8
+#define C_VATTR       0x1   /* Validity of vattr in inode */
+#define C_PURGE       0x8
 #define C_ZAPDIR      0x10
+#define C_DYING       0x4   /* from venus (which died) */
 #define C_INITED      0x20
+#define C_FLUSH       0x2   /* used after a flush */
 
 int coda_cnode_make(struct inode **, struct ViceFid *, struct super_block *);
 int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
diff -u --recursive --new-file v2.1.131/linux/include/linux/coda_linux.h linux/include/linux/coda_linux.h
--- v2.1.131/linux/include/linux/coda_linux.h	Sat Sep  5 16:46:41 1998
+++ linux/include/linux/coda_linux.h	Mon Dec 21 14:23:28 1998
@@ -71,16 +71,20 @@
 #define NB_SFS_SIZ 0x895440
 
 /* cache.c */
-void coda_purge_children(struct inode *);
+void coda_purge_children(struct inode *, int);
 void coda_purge_dentries(struct inode *);
 
+/* sysctl.h */
+void coda_sysctl_init(void);
+void coda_sysctl_clean(void);
+
 
 /* debugging masks */
 #define D_SUPER     1   /* print results returned by Venus */ 
 #define D_INODE     2   /* print entry and exit into procedure */
-#define D_FILE      4   /* print malloc, de-alloc information */
+#define D_FILE      4   
 #define D_CACHE     8   /* cache debugging */
-#define D_MALLOC    16
+#define D_MALLOC    16  /* print malloc, de-alloc information */
 #define D_CNODE     32
 #define D_UPCALL    64  /* up and downcall debugging */
 #define D_PSDEV    128  
diff -u --recursive --new-file v2.1.131/linux/include/linux/coda_psdev.h linux/include/linux/coda_psdev.h
--- v2.1.131/linux/include/linux/coda_psdev.h	Thu Jul 16 18:09:29 1998
+++ linux/include/linux/coda_psdev.h	Mon Dec 21 14:23:28 1998
@@ -4,16 +4,8 @@
 #define CODA_PSDEV_MAJOR 67
 #define MAX_CODADEVS  5	   /* how many do we allow */
 
-extern struct vcomm psdev_vcomm[];
-
-/* queue stuff; the rest is static to psdev.c */
-struct queue {
-    struct queue *forw, *back;
-};
-void coda_q_insert(struct queue *el, struct queue *q);
-void coda_q_remove(struct queue *q);
-
-
+extern struct venus_comm coda_upc_comm;
+extern struct coda_sb_info coda_super_info;
 #define CODA_SUPER_MAGIC	0x73757245
 
 struct coda_sb_info
@@ -21,31 +13,23 @@
 	struct inode *      sbi_psdev;     /* /dev/cfs? Venus/kernel device */
 	struct inode *      sbi_ctlcp;     /* control magic file */
 	int                 sbi_refct;
-	struct vcomm *      sbi_vcomm;
+	struct venus_comm *      sbi_vcomm;
 	struct inode *      sbi_root;
+	struct super_block *sbi_sb;
 	struct list_head    sbi_cchead;
 	struct list_head    sbi_volroothead;
 };
 
-/* communication pending/processing queues queues */
-struct vcomm {
+/* communication pending/processing queues */
+struct venus_comm {
 	u_long		    vc_seq;
 	struct wait_queue  *vc_waitq; /* Venus wait queue */
-	struct queue	    vc_pending;
-	struct queue	    vc_processing;
-	struct super_block *vc_sb;
+	struct list_head    vc_pending;
+	struct list_head    vc_processing;
 	int                 vc_inuse;
+	pid_t               vc_pid;   /* Venus pid */
 };
 
-static inline int vcomm_open(struct vcomm *vcp)
-{
-        return ((vcp)->vc_pending.forw != NULL);
-}
-
-static inline void mark_vcomm_closed(struct vcomm *vcp)
-{
-        (vcp)->vc_pending.forw = NULL;
-}
 
 static inline struct coda_sb_info *coda_sbp(struct super_block *sb)
 {
@@ -67,7 +51,8 @@
 int venus_lookup(struct super_block *sb, struct ViceFid *fid, 
 		    const char *name, int length, int *type, 
 		    struct ViceFid *resfid);
-int venus_release(struct super_block *sb, struct ViceFid *fid, int flags);
+int venus_release(struct super_block *sb, struct ViceFid *fid, int flags,
+		  struct coda_cred *);
 int venus_open(struct super_block *sb, struct ViceFid *fid,
 		  int flags, ino_t *ino, dev_t *dev);
 int venus_mkdir(struct super_block *sb, struct ViceFid *dirfid, 
@@ -100,18 +85,22 @@
 /* messages between coda filesystem in kernel and Venus */
 extern int coda_hard;
 extern unsigned long coda_timeout;
-struct vmsg {
-	struct queue        vm_chain;
-	caddr_t	        vm_data;
-	u_short	        vm_flags;
-	u_short             vm_inSize;  /* Size is at most 5000 bytes */
-	u_short	        vm_outSize;
-	u_short	        vm_opcode;  /* copied from data to save lookup */
-	int		        vm_unique;
-	struct wait_queue  *vm_sleep;   /* process' wait queue */
-	unsigned long       vm_posttime;
+struct upc_req {
+	struct list_head    uc_chain;
+	caddr_t	            uc_data;
+	u_short	            uc_flags;
+	u_short             uc_inSize;  /* Size is at most 5000 bytes */
+	u_short	            uc_outSize;
+	u_short	            uc_opcode;  /* copied from data to save lookup */
+	int		    uc_unique;
+	struct wait_queue  *uc_sleep;   /* process' wait queue */
+	unsigned long       uc_posttime;
 };
 
+#define REQ_ASYNC  0x1
+#define REQ_READ   0x2
+#define REQ_WRITE  0x4
+
 
 /*
  * Statistics
@@ -119,7 +108,7 @@
 struct coda_upcallstats {
 	int	ncalls;			/* client requests */
 	int	nbadcalls;		/* upcall failures */
-	int	reqs[CFS_NCALLS];	/* count of each request */
+	int	reqs[CODA_NCALLS];	/* count of each request */
 } ;
 
 extern struct coda_upcallstats coda_callstats;
@@ -127,7 +116,7 @@
 static inline void clstats(int opcode)
 {
     coda_callstats.ncalls++;
-    if ( (0 <= opcode) && (opcode <= CFS_NCALLS) )
+    if ( (0 <= opcode) && (opcode <= CODA_NCALLS) )
 	coda_callstats.reqs[opcode]++;
     else
 	printk("clstats called with bad opcode %d\n", opcode); 
diff -u --recursive --new-file v2.1.131/linux/include/linux/fb.h linux/include/linux/fb.h
--- v2.1.131/linux/include/linux/fb.h	Thu Nov 19 09:56:29 1998
+++ linux/include/linux/fb.h	Mon Dec 21 14:48:04 1998
@@ -35,6 +35,8 @@
 #define FB_AUX_TEXT_MDA		0	/* Monochrome text */
 #define FB_AUX_TEXT_CGA		1	/* CGA/EGA/VGA Color text */
 #define FB_AUX_TEXT_S3_MMIO	2	/* S3 MMIO fasttext */
+#define FB_AUX_TEXT_MGA_STEP16	3	/* MGA Millenium I: text, attr, 14 reserved bytes */
+#define FB_AUX_TEXT_MGA_STEP8	4	/* other MGAs:      text, attr,  6 reserved bytes */
 
 #define FB_VISUAL_MONO01		0	/* Monochr. 1=Black 0=White */
 #define FB_VISUAL_MONO10		1	/* Monochr. 1=White 0=Black */
diff -u --recursive --new-file v2.1.131/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.1.131/linux/include/linux/fs.h	Thu Nov 12 16:21:24 1998
+++ linux/include/linux/fs.h	Tue Dec 22 10:44:25 1998
@@ -176,8 +176,6 @@
 #define BH_Dirty	1	/* 1 if the buffer is dirty */
 #define BH_Lock		2	/* 1 if the buffer is locked */
 #define BH_Req		3	/* 0 if the buffer has been invalidated */
-#define BH_Touched	4	/* 1 if the buffer has been touched (aging) */
-#define BH_Has_aged	5	/* 1 if the buffer has been aged (aging) */
 #define BH_Protected	6	/* 1 if the buffer is protected */
 
 /*
@@ -248,21 +246,19 @@
 	return test_bit(BH_Req, &bh->b_state);
 }
 
-static inline int buffer_touched(struct buffer_head * bh)
-{
-	return test_bit(BH_Touched, &bh->b_state);
-}
-
-static inline int buffer_has_aged(struct buffer_head * bh)
-{
-	return test_bit(BH_Has_aged, &bh->b_state);
-}
-
 static inline int buffer_protected(struct buffer_head * bh)
 {
 	return test_bit(BH_Protected, &bh->b_state);
 }
 
+/*
+ * Deprecated - we don't keep per-buffer reference flags
+ * any more.
+ */
+#define buffer_page(bh)		(mem_map + MAP_NR((bh)->b_data))
+#define buffer_touched(bh)	(PageReferenced(buffer_page(bh)))
+#define touch_buffer(bh)	set_bit(PG_referenced, buffer_page(bh))
+
 #include <linux/pipe_fs_i.h>
 #include <linux/minix_fs_i.h>
 #include <linux/ext2_fs_i.h>
@@ -560,6 +556,13 @@
 };
 
 /*
+ * VFS helper functions..
+ */
+extern int vfs_rmdir(struct inode *, struct dentry *);
+extern int vfs_unlink(struct inode *, struct dentry *);
+extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
+
+/*
  * This is the "filldir" function type, used by readdir() to let
  * the kernel specify what kind of dirent layout it wants to have.
  * This allows the kernel to read directories into kernel space or
@@ -729,7 +732,7 @@
 
 extern void refile_buffer(struct buffer_head * buf);
 extern void set_writetime(struct buffer_head * buf, int flag);
-extern int try_to_free_buffer(struct buffer_head*, struct buffer_head**, int);
+extern int try_to_free_buffer(struct buffer_head*, struct buffer_head**);
 
 extern int nr_buffers;
 extern int buffermem;
diff -u --recursive --new-file v2.1.131/linux/include/linux/if_arp.h linux/include/linux/if_arp.h
--- v2.1.131/linux/include/linux/if_arp.h	Fri Jul 31 17:07:27 1998
+++ linux/include/linux/if_arp.h	Tue Dec 22 10:46:08 1998
@@ -65,6 +65,7 @@
 #define ARPHRD_HIPPI	780		/* High Performance Parallel Interface */
 #define ARPHRD_ASH	781		/* Nexus 64Mbps Ash		*/
 #define ARPHRD_ECONET	782		/* Acorn Econet			*/
+#define ARPHRD_IRDA 	783		/* Linux/IR			*/
 
 /* ARP protocol opcodes. */
 #define	ARPOP_REQUEST	1		/* ARP request			*/
diff -u --recursive --new-file v2.1.131/linux/include/linux/if_ether.h linux/include/linux/if_ether.h
--- v2.1.131/linux/include/linux/if_ether.h	Tue Jun 23 10:01:29 1998
+++ linux/include/linux/if_ether.h	Wed Dec 16 13:35:50 1998
@@ -73,6 +73,8 @@
 #define ETH_P_PPPTALK	0x0010		/* Dummy type for Atalk over PPP*/
 #define ETH_P_TR_802_2	0x0011		/* 802.2 frames 		*/
 #define ETH_P_MOBITEX	0x0015		/* Mobitex (kaz@cafe.net)	*/
+#define ETH_P_CONTROL	0x0016		/* Card specific control frames */
+#define ETH_P_IRDA	0x0017		/* Linux/IR			*/
 
 /*
  *	This is an Ethernet frame header.
diff -u --recursive --new-file v2.1.131/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.1.131/linux/include/linux/interrupt.h	Fri Jul 31 17:05:53 1998
+++ linux/include/linux/interrupt.h	Tue Dec 22 10:44:25 1998
@@ -17,7 +17,7 @@
 
 extern volatile unsigned char bh_running;
 
-extern int bh_mask_count[32];
+extern atomic_t bh_mask_count[32];
 extern unsigned long bh_active;
 extern unsigned long bh_mask;
 extern void (*bh_base[32])(void);
@@ -43,7 +43,8 @@
 	CYCLADES_BH,
 	CM206_BH,
 	JS_BH,
-	MACSERIAL_BH
+	MACSERIAL_BH,
+	ISICOM_BH
 };
 
 #include <asm/hardirq.h>
diff -u --recursive --new-file v2.1.131/linux/include/linux/isicom.h linux/include/linux/isicom.h
--- v2.1.131/linux/include/linux/isicom.h	Wed Dec 31 16:00:00 1969
+++ linux/include/linux/isicom.h	Thu Dec 17 16:21:29 1998
@@ -0,0 +1,302 @@
+#ifndef _LINUX_ISICOM_H
+#define _LINUX_ISICOM_H
+
+/*#define		ISICOM_DEBUG*/
+/*#define		ISICOM_DEBUG_DTR_RTS*/
+
+
+/*
+ *	Firmware Loader definitions ...
+ */
+ 
+#define		__MultiTech		('M'<<8)
+#define		MIOCTL_LOAD_FIRMWARE	(__MultiTech | 0x01)
+#define         MIOCTL_READ_FIRMWARE    (__MultiTech | 0x02)
+#define         MIOCTL_XFER_CTRL	(__MultiTech | 0x03)
+#define         MIOCTL_RESET_CARD	(__MultiTech | 0x04)
+
+#define		DATA_SIZE	16
+
+typedef	struct	{
+		unsigned short	exec_segment;
+		unsigned short	exec_addr;
+}	exec_record;
+
+typedef	struct	{
+		int		board;		/* Board to load */
+		unsigned short	addr;
+		unsigned short	count;
+}	bin_header;
+
+typedef	struct	{
+		int		board;		/* Board to load */
+		unsigned short	addr;
+		unsigned short	count;
+		unsigned short	segment;
+		unsigned char	bin_data[DATA_SIZE];
+}	bin_frame;
+
+#ifdef __KERNEL__
+
+#define		YES	1
+#define		NO	0
+
+#define		ISILOAD_MISC_MINOR	155	/* /dev/isctl */
+#define		ISILOAD_NAME		"ISILoad"
+
+/*	
+ *  ISICOM Driver definitions ...
+ *
+ */
+
+#define		ISICOM_NAME	"ISICom"
+
+/*
+ *	These are now officially allocated numbers
+ */
+
+#define		ISICOM_NMAJOR	112	/* normal  */
+#define		ISICOM_CMAJOR	113	/* callout */
+#define		ISICOM_MAGIC	(('M' << 8) | 'T')
+
+#define		WAKEUP_CHARS	256	/* hard coded for now	*/ 
+#define		TX_SIZE		254 
+ 
+#define		BOARD_COUNT	4
+#define		PORT_COUNT	(BOARD_COUNT*16)
+
+#define		SERIAL_TYPE_NORMAL	1
+#define		SERIAL_TYPE_CALLOUT	2
+
+/*   character sizes  */
+
+#define		ISICOM_CS5		0x0000
+#define		ISICOM_CS6		0x0001
+#define		ISICOM_CS7		0x0002
+#define		ISICOM_CS8		0x0003
+
+/* stop bits */
+
+#define		ISICOM_1SB		0x0000
+#define		ISICOM_2SB		0x0004
+
+/* parity */
+
+#define		ISICOM_NOPAR		0x0000
+#define		ISICOM_ODPAR		0x0008
+#define		ISICOM_EVPAR		0x0018
+
+/* flow control */
+
+#define		ISICOM_CTSRTS		0x03
+#define		ISICOM_INITIATE_XONXOFF	0x04
+#define		ISICOM_RESPOND_XONXOFF	0x08
+
+#define InterruptTheCard(base) (outw(0,(base)+0xc)) 
+#define ClearInterrupt(base) (inw((base)+0x0a))	
+
+#define	BOARD(line)  (((line) >> 4) & 0x3)
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+
+	/*	isi kill queue bitmap	*/
+	
+#define		ISICOM_KILLTX		0x01
+#define		ISICOM_KILLRX		0x02
+
+	/* isi_board status bitmap */
+	
+#define		FIRMWARE_LOADED		0x0001
+#define		BOARD_ACTIVE		0x0002
+
+ 	/* isi_port status bitmap  */
+
+#define		ISI_CTS			0x1000
+#define		ISI_DSR			0x2000
+#define		ISI_RI			0x4000
+#define		ISI_DCD			0x8000
+#define		ISI_DTR			0x0100
+#define		ISI_RTS			0x0200
+
+
+#define		ISI_TXOK		0x0001 
+ 
+struct	isi_board {
+	unsigned short		base;
+	unsigned char		irq;
+	unsigned char		port_count;
+	unsigned short		status;
+	unsigned short		port_status; /* each bit represents a single port */
+	unsigned short		shift_count;
+	struct isi_port		* ports;
+	signed char		count;
+};
+
+struct	isi_port {
+	unsigned short		magic;
+	unsigned int		flags;
+	int			count;
+	int			blocked_open;
+	int			close_delay;
+	unsigned short		channel;
+	unsigned short		status;
+	unsigned short		closing_wait;
+	long 			session;
+	long			pgrp;
+	struct isi_board	* card;
+	struct tty_struct 	* tty;
+	struct wait_queue	* close_wait;
+	struct wait_queue	* open_wait;
+	struct tq_struct	hangup_tq;
+	struct tq_struct	bh_tqueue;
+	unsigned char		* xmit_buf;
+	int			xmit_head;
+	int			xmit_tail;
+	int			xmit_cnt;
+	struct termios 		normal_termios;
+	struct termios		callout_termios;
+};
+
+
+/*
+ *  ISI Card specific ops ...
+ */
+ 
+extern inline void raise_dtr(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG_DTR_RTS	
+	printk(KERN_DEBUG "ISICOM: raise_dtr.\n");
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x0504, base);
+	InterruptTheCard(base);
+	port->status |= ISI_DTR;
+}
+
+extern inline void drop_dtr(struct isi_port * port)
+{	
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG_DTR_RTS	
+	printk(KERN_DEBUG "ISICOM: drop_dtr.\n");
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x0404, base);
+	InterruptTheCard(base);	
+	port->status &= ~ISI_DTR;
+}
+extern inline void raise_rts(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in raise_rts.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG_DTR_RTS	
+	printk(KERN_DEBUG "ISICOM: raise_rts.\n");
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x0a04, base);
+	InterruptTheCard(base);	
+	port->status |= ISI_RTS;
+}
+extern inline void drop_rts(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in drop_rts.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG_DTR_RTS	
+	printk(KERN_DEBUG "ISICOM: drop_rts.\n");
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x0804, base);
+	InterruptTheCard(base);	
+	port->status &= ~ISI_RTS;
+}
+extern inline void raise_dtr_rts(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in raise_dtr_rts.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG_DTR_RTS	
+	printk(KERN_DEBUG "ISICOM: raise_dtr_rts.\n");
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x0f04, base);
+	InterruptTheCard(base);
+	port->status |= (ISI_DTR | ISI_RTS);
+}
+extern inline void drop_dtr_rts(struct isi_port * port)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in drop_dtr_rts.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG_DTR_RTS	
+	printk(KERN_DEBUG "ISICOM: drop_dtr_rts.\n");
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw(0x0c04, base);
+	InterruptTheCard(base);	
+	port->status &= ~(ISI_RTS | ISI_DTR);
+}
+
+extern inline void kill_queue(struct isi_port * port, short queue)
+{
+	struct isi_board * card = port->card;
+	unsigned short base = card->base;
+	unsigned char channel = port->channel;
+	short wait=300;
+	while(((inw(base+0x0e) & 0x01) == 0) && (wait-- > 0));
+	if (wait <= 0) {
+		printk(KERN_WARNING "ISICOM: Card found busy in kill_queue.\n");
+		return;
+	}
+#ifdef ISICOM_DEBUG	
+	printk(KERN_DEBUG "ISICOM: kill_queue 0x%x.\n", queue);
+#endif	
+	outw(0x8000 | (channel << card->shift_count) | 0x02 , base);
+	outw((queue << 8) | 0x06, base);
+	InterruptTheCard(base);	
+}
+
+#endif	/*	__KERNEL__	*/
+
+#endif	/*	ISICOM_H	*/
+
diff -u --recursive --new-file v2.1.131/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.1.131/linux/include/linux/mm.h	Thu Nov 19 09:56:29 1998
+++ linux/include/linux/mm.h	Tue Dec 22 10:44:25 1998
@@ -11,6 +11,7 @@
 extern unsigned long max_mapnr;
 extern unsigned long num_physpages;
 extern void * high_memory;
+extern int page_cluster;
 
 #include <asm/page.h>
 #include <asm/atomic.h>
diff -u --recursive --new-file v2.1.131/linux/include/linux/nfs_fs.h linux/include/linux/nfs_fs.h
--- v2.1.131/linux/include/linux/nfs_fs.h	Wed Dec 16 10:32:56 1998
+++ linux/include/linux/nfs_fs.h	Tue Dec 22 10:44:45 1998
@@ -222,13 +222,13 @@
 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);
 
 /*
  * Invalidate write-backs, possibly trying to write them
  * back first..
  */
 extern void nfs_inval(struct inode *);
-extern int  nfs_truncate_dirty_pages(struct inode *, unsigned long);
 extern int  nfs_updatepage(struct file *, struct page *, unsigned long, unsigned int, int);
 
 /*
diff -u --recursive --new-file v2.1.131/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.1.131/linux/include/linux/pci.h	Wed Dec 16 10:32:56 1998
+++ linux/include/linux/pci.h	Tue Dec 22 10:44:25 1998
@@ -408,7 +408,11 @@
 #define PCI_DEVICE_ID_MATROX_MYS	0x051A
 #define PCI_DEVICE_ID_MATROX_MIL_2	0x051b
 #define PCI_DEVICE_ID_MATROX_MIL_2_AGP	0x051f
+#define PCI_DEVICE_ID_MATROX_G200_PCI   0x0520
+#define PCI_DEVICE_ID_MATROX_G200_AGP   0x0521
 #define PCI_DEVICE_ID_MATROX_MGA_IMP	0x0d10
+#define PCI_DEVICE_ID_MATROX_G100_MM    0x1000
+#define PCI_DEVICE_ID_MATROX_G100_AGP   0x1001
 
 #define PCI_VENDOR_ID_CT		0x102c
 #define PCI_DEVICE_ID_CT_65545		0x00d8
@@ -720,6 +724,7 @@
 #define PCI_DEVICE_ID_VIA_82C586_0	0x0586
 #define PCI_DEVICE_ID_VIA_82C595	0x0595
 #define PCI_DEVICE_ID_VIA_82C597_0	0x0597
+#define PCI_DEVICE_ID_VIA_82C598_0      0x0598
 #define PCI_DEVICE_ID_VIA_82C926	0x0926
 #define PCI_DEVICE_ID_VIA_82C416	0x1571
 #define PCI_DEVICE_ID_VIA_82C595_97	0x1595
@@ -727,6 +732,7 @@
 #define PCI_DEVICE_ID_VIA_82C586_3	0x3040
 #define PCI_DEVICE_ID_VIA_86C100A	0x6100
 #define PCI_DEVICE_ID_VIA_82C597_1	0x8597
+#define PCI_DEVICE_ID_VIA_82C598_1      0x8598
 
 #define PCI_VENDOR_ID_VORTEX		0x1119
 #define PCI_DEVICE_ID_VORTEX_GDT60x0	0x0000
diff -u --recursive --new-file v2.1.131/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.1.131/linux/include/linux/proc_fs.h	Fri Nov 27 13:09:29 1998
+++ linux/include/linux/proc_fs.h	Tue Dec 22 10:44:25 1998
@@ -52,7 +52,8 @@
 	PROC_STRAM,
 	PROC_SOUND,
 	PROC_MTRR, /* whether enabled or not */
-	PROC_FS
+	PROC_FS,
+	PROC_SWAPSTATS
 };
 
 enum pid_directory_inos {
@@ -139,10 +140,13 @@
 	PROC_NET_DN_L2,
 	PROC_NET_DN_CACHE,
 	PROC_NET_DN_SKT,
+	PROC_NET_DN_FW,
+	PROC_NET_DN_RAW,
 	PROC_NET_NETSTAT,
 	PROC_NET_IPFW_CHAINS,
 	PROC_NET_IPFW_CHAIN_NAMES,
 	PROC_NET_AT_AARP,
+	PROC_NET_BRIDGE,
 	PROC_NET_LAST
 };
 
@@ -167,6 +171,7 @@
 	PROC_SCSI_PAS16,
 	PROC_SCSI_QLOGICFAS,
 	PROC_SCSI_QLOGICISP,
+	PROC_SCSI_QLOGICFC,
 	PROC_SCSI_SEAGATE,
 	PROC_SCSI_T128,
 	PROC_SCSI_NCR53C7xx,
@@ -180,7 +185,9 @@
 	PROC_SCSI_AM53C974,
 	PROC_SCSI_SSC,
 	PROC_SCSI_NCR53C406A,
+	PROC_SCSI_MEGARAID,
 	PROC_SCSI_PPA,
+	PROC_SCSI_ATP870U,
 	PROC_SCSI_ESP,
 	PROC_SCSI_QLOGICPTI,
 	PROC_SCSI_AMIGA7XX,
@@ -195,6 +202,7 @@
 	PROC_SCSI_MESH,
 	PROC_SCSI_53C94,
 	PROC_SCSI_PLUTO,
+	PROC_SCSI_INI9100U,
 	PROC_SCSI_SCSI_DEBUG,	
 	PROC_SCSI_NOT_PRESENT,
 	PROC_SCSI_FILE,                        /* I'm assuming here that we */
diff -u --recursive --new-file v2.1.131/linux/include/linux/scc.h linux/include/linux/scc.h
--- v2.1.131/linux/include/linux/scc.h	Wed Dec  3 17:35:22 1997
+++ linux/include/linux/scc.h	Fri Dec 18 13:57:21 1998
@@ -82,8 +82,8 @@
 
 /* channel grouping */
 
-#define RXGROUP		0x100	/* if set, only tx when all channels clear */
-#define TXGROUP		0x200	/* if set, don't transmit simultaneously */
+#define RXGROUP		0100	/* if set, only tx when all channels clear */
+#define TXGROUP		0200	/* if set, don't transmit simultaneously */
 
 /* Tx/Rx clock sources */
 
@@ -237,6 +237,7 @@
 
 	unsigned char wreg[16]; 	/* Copy of last written value in WRx */
 	unsigned char status;		/* Copy of R0 at last external interrupt */
+	unsigned char dcd;		/* DCD status */
 
         struct scc_kiss kiss;		/* control structure for KISS params */
         struct scc_stat stat;		/* statistical information */
diff -u --recursive --new-file v2.1.131/linux/include/linux/shm.h linux/include/linux/shm.h
--- v2.1.131/linux/include/linux/shm.h	Fri Oct 23 22:01:27 1998
+++ linux/include/linux/shm.h	Fri Dec 18 09:37:22 1998
@@ -14,6 +14,9 @@
 	__kernel_ipc_pid_t	shm_cpid;	/* pid of creator */
 	__kernel_ipc_pid_t	shm_lpid;	/* pid of last operator */
 	unsigned short		shm_nattch;	/* no. of current attaches */
+	unsigned short 		shm_unused;	/* compatibility */
+	void 			*shm_unused2;	/* ditto - used by DIPC */
+	void			*shm_unused3;	/* unused */
 };
 
 struct shmid_kernel
diff -u --recursive --new-file v2.1.131/linux/include/linux/socket.h linux/include/linux/socket.h
--- v2.1.131/linux/include/linux/socket.h	Sun Nov  8 14:03:11 1998
+++ linux/include/linux/socket.h	Wed Dec 16 13:35:50 1998
@@ -166,6 +166,7 @@
 #define AF_ECONET	19	/* Acorn Econet			*/
 #define AF_ATMSVC	20	/* ATM SVCs			*/
 #define AF_SNA		22	/* Linux SNA Project (nutters!) */
+#define AF_IRDA		23	/* IRDA sockets			*/
 #define AF_MAX		32	/* For now.. */
 
 /* Protocol families, same as address families. */
@@ -193,6 +194,7 @@
 #define PF_ECONET	AF_ECONET
 #define PF_ATMSVC	AF_ATMSVC
 #define PF_SNA		AF_SNA
+#define PF_IRDA		AF_IRDA
 
 #define PF_MAX		AF_MAX
 
@@ -206,6 +208,7 @@
 #define MSG_OOB		1
 #define MSG_PEEK	2
 #define MSG_DONTROUTE	4
+#define MSG_TRYHARD     4       /* Synonym for MSG_DONTROUTE for DECnet */
 #define MSG_CTRUNC	8
 #define MSG_PROXY	0x10	/* Supply or ask second address. */
 #define MSG_TRUNC	0x20
diff -u --recursive --new-file v2.1.131/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.1.131/linux/include/linux/swap.h	Wed Dec 16 10:32:56 1998
+++ linux/include/linux/swap.h	Tue Dec 22 10:44:28 1998
@@ -61,6 +61,15 @@
 extern unsigned long page_cache_size;
 extern int buffermem;
 
+struct swap_stats 
+{
+	long	proc_freepage_attempts;
+	long	proc_freepage_successes;
+	long	kswap_freepage_attempts;
+	long	kswap_freepage_successes;
+};
+extern struct swap_stats swap_stats;
+
 /* Incomplete types for prototype declarations: */
 struct task_struct;
 struct vm_area_struct;
@@ -69,6 +78,9 @@
 /* linux/ipc/shm.c */
 extern int shm_swap (int, int);
 
+/* linux/mm/swap.c */
+extern void swap_setup (void);
+
 /* linux/mm/vmscan.c */
 extern int try_to_free_pages(unsigned int gfp_mask, int count);
 
@@ -87,6 +99,7 @@
 extern int add_to_swap_cache(struct page *, unsigned long);
 extern int swap_duplicate(unsigned long);
 extern int swap_check_entry(unsigned long);
+struct page * lookup_swap_cache(unsigned long);
 extern struct page * read_swap_cache_async(unsigned long, int);
 #define read_swap_cache(entry) read_swap_cache_async(entry, 1);
 extern int FASTCALL(swap_count(unsigned long));
diff -u --recursive --new-file v2.1.131/linux/include/linux/swapctl.h linux/include/linux/swapctl.h
--- v2.1.131/linux/include/linux/swapctl.h	Thu Nov 19 09:56:29 1998
+++ linux/include/linux/swapctl.h	Tue Dec 22 10:44:44 1998
@@ -22,11 +22,19 @@
 
 typedef struct swapstat_v1
 {
-	unsigned int	wakeups;
-	unsigned int	pages_reclaimed;
-	unsigned int	pages_shm;
-	unsigned int	pages_mmap;
-	unsigned int	pages_swap;
+	unsigned long	wakeups;
+	unsigned long	pages_reclaimed;
+	unsigned long	pages_shm;
+	unsigned long	pages_mmap;
+	unsigned long	pages_swap;
+
+	unsigned long	gfp_freepage_attempts;
+	unsigned long	gfp_freepage_successes;
+	unsigned long	gfp_shrink_attempts;
+	unsigned long	gfp_shrink_successes;
+	unsigned long	kswap_freepage_attempts;
+	unsigned long	kswap_freepage_successes;
+	unsigned long	kswap_wakeups[4];
 } swapstat_v1;
 typedef swapstat_v1 swapstat_t;
 extern swapstat_t swapstats;
diff -u --recursive --new-file v2.1.131/linux/include/linux/sysctl.h linux/include/linux/sysctl.h
--- v2.1.131/linux/include/linux/sysctl.h	Thu Nov 12 16:21:24 1998
+++ linux/include/linux/sysctl.h	Sun Dec 20 06:00:40 1998
@@ -56,7 +56,7 @@
 	CTL_PROC=4,		/* Process info */
 	CTL_FS=5,		/* Filesystems */
 	CTL_DEBUG=6,		/* Debugging */
-	CTL_DEV=7,		/* Devices */
+	CTL_DEV=7		/* Devices */
 };
 
 
@@ -89,6 +89,14 @@
 	KERN_SG_BIG_BUFF=29,
 	KERN_ACCT=30,		/* BSD process accounting parameters */
 	KERN_PPC_L2CR=31,	/* l2cr register on PPC */
+
+	KERN_RTSIGNR=32,	/* Number of rt sigs queued */
+	KERN_RTSIGMAX=33,	/* Max queuable */
+	
+	KERN_SHMMAX=34,         /* int: Maximum shared memory segment */
+	KERN_MSGMAX=35,         /* int: Maximum size of a messege */
+	KERN_MSGMNB=36,         /* int: Maximum message queue size */
+	KERN_MSGPOOL=37         /* int: Maximum system message pool size */
 };
 
 
@@ -103,7 +111,8 @@
 	VM_BUFFERMEM=6,		/* struct: Set buffer memory thresholds */
 	VM_PAGECACHE=7,		/* struct: Set cache memory thresholds */
 	VM_PAGERDAEMON=8,	/* struct: Control kswapd behaviour */
-	VM_PGT_CACHE=9		/* struct: Set page table cache parameters */
+	VM_PGT_CACHE=9,		/* struct: Set page table cache parameters */
+	VM_PAGE_CLUSTER=10	/* int: set log2 number of pages to swap together */
 };
 
 
@@ -140,7 +149,7 @@
 	NET_CORE_FASTROUTE=7,
 	NET_CORE_MSG_COST=8,
 	NET_CORE_MSG_BURST=9,
-	NET_CORE_OPTMEM_MAX=10,
+	NET_CORE_OPTMEM_MAX=10
 };
 
 /* /proc/sys/net/ethernet */
@@ -152,7 +161,7 @@
 enum
 {
 	NET_UNIX_DESTROY_DELAY=1,
-	NET_UNIX_DELETE_DELAY=2,
+	NET_UNIX_DELETE_DELAY=2
 };
 
 /* /proc/sys/net/ipv4 */
@@ -198,6 +207,7 @@
 	NET_IPV4_ICMP_TIMEEXCEED_RATE=61,
 	NET_IPV4_ICMP_PARAMPROB_RATE=62,
 	NET_IPV4_ICMP_ECHOREPLY_RATE=63,
+	NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES=64
 };
 
 enum {
@@ -214,13 +224,13 @@
 	NET_IPV4_ROUTE_REDIRECT_SILENCE=11,
 	NET_IPV4_ROUTE_ERROR_COST=12,
 	NET_IPV4_ROUTE_ERROR_BURST=13,
-	NET_IPV4_ROUTE_GC_ELASTICITY=14,
+	NET_IPV4_ROUTE_GC_ELASTICITY=14
 };
 
 enum
 {
 	NET_PROTO_CONF_ALL=-2,
-	NET_PROTO_CONF_DEFAULT=-3,
+	NET_PROTO_CONF_DEFAULT=-3
 
 	/* And device ifindices ... */
 };
@@ -237,14 +247,14 @@
 	NET_IPV4_CONF_RP_FILTER=8,
 	NET_IPV4_CONF_ACCEPT_SOURCE_ROUTE=9,
 	NET_IPV4_CONF_BOOTP_RELAY=10,
-	NET_IPV4_CONF_LOG_MARTIANS=11,
+	NET_IPV4_CONF_LOG_MARTIANS=11
 };
 
 /* /proc/sys/net/ipv6 */
 enum {
 	NET_IPV6_CONF=16,
 	NET_IPV6_NEIGH=17,
-	NET_IPV6_ROUTE=18,
+	NET_IPV6_ROUTE=18
 };
 
 enum {
@@ -254,7 +264,7 @@
 	NET_IPV6_ROUTE_GC_MIN_INTERVAL=4,
 	NET_IPV6_ROUTE_GC_TIMEOUT=5,
 	NET_IPV6_ROUTE_GC_INTERVAL=6,
-	NET_IPV6_ROUTE_GC_ELASTICITY=7,
+	NET_IPV6_ROUTE_GC_ELASTICITY=7
 };
 
 enum {
@@ -267,7 +277,7 @@
 	NET_IPV6_DAD_TRANSMITS=7,
 	NET_IPV6_RTR_SOLICITS=8,
 	NET_IPV6_RTR_SOLICIT_INTERVAL=9,
-	NET_IPV6_RTR_SOLICIT_DELAY=10,
+	NET_IPV6_RTR_SOLICIT_DELAY=10
 };
 
 /* /proc/sys/net/<protocol>/neigh/<dev> */
@@ -298,7 +308,7 @@
 	NET_ATALK_AARP_EXPIRY_TIME=1,
 	NET_ATALK_AARP_TICK_TIME=2,
 	NET_ATALK_AARP_RETRANSMIT_LIMIT=3,
-	NET_ATALK_AARP_RESOLVE_TIME=4,
+	NET_ATALK_AARP_RESOLVE_TIME=4
 };
 
 
@@ -346,7 +356,7 @@
 	NET_ROSE_LINK_FAIL_TIMEOUT=7,
 	NET_ROSE_MAX_VCS=8,
 	NET_ROSE_WINDOW_SIZE=9,
-	NET_ROSE_NO_ACTIVITY_TIMEOUT=10,
+	NET_ROSE_NO_ACTIVITY_TIMEOUT=10
 };
 
 /* /proc/sys/net/x25 */
@@ -366,12 +376,11 @@
 
 /* /proc/sys/net/decnet */
 enum {
-	NET_DECNET_DEF_T3_BROADCAST=1,
-	NET_DECNET_DEF_T3_POINTTOPOINT=2,
-	NET_DECNET_DEF_T1=3,
-	NET_DECNET_DEF_BCT1=4,
-	NET_DECNET_CACHETIMEOUT=5,
-	NET_DECNET_DEBUG_LEVEL=6
+	NET_DECNET_NODE_TYPE=1,
+	NET_DECNET_NODE_ADDRESS=2,
+	NET_DECNET_NODE_NAME=3,
+	NET_DECNET_DEFAULT_DEVICE=4,
+	NET_DECNET_DEBUG_LEVEL=255
 };
 
 /* CTL_PROC names: */
@@ -388,7 +397,7 @@
 	FS_MAXFILE=7,	/* int:maximum number of filedescriptors that can be allocated */
 	FS_DENTRY=8,
 	FS_NRSUPER=9,	/* int:current number of allocated super_blocks */
-	FS_MAXSUPER=10,	/* int:maximum number of super_blocks that can be allocated */
+	FS_MAXSUPER=10	/* int:maximum number of super_blocks that can be allocated */
 };
 
 /* CTL_DEBUG names: */
@@ -396,12 +405,12 @@
 /* CTL_DEV names: */
 enum {
 	DEV_CDROM=1,
-	DEV_HWMON=2,
+	DEV_HWMON=2
 };
 
 /* /proc/sys/dev/cdrom */
 enum {
-	DEV_CDROM_INFO=1,
+	DEV_CDROM_INFO=1
 };
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.1.131/linux/include/linux/tasks.h linux/include/linux/tasks.h
--- v2.1.131/linux/include/linux/tasks.h	Sun Jan 26 03:40:46 1997
+++ linux/include/linux/tasks.h	Tue Dec 22 10:44:25 1998
@@ -11,7 +11,7 @@
 #define NR_CPUS 1
 #endif
 
-#define NR_TASKS	512
+#define NR_TASKS	512	/* On x86 Max 4092, or 4090 w/APM configured. */
 
 #define MAX_TASKS_PER_USER (NR_TASKS/2)
 #define MIN_TASKS_LEFT_FOR_ROOT 4
diff -u --recursive --new-file v2.1.131/linux/include/linux/videodev.h linux/include/linux/videodev.h
--- v2.1.131/linux/include/linux/videodev.h	Fri Oct 23 22:01:27 1998
+++ linux/include/linux/videodev.h	Wed Dec 16 13:35:50 1998
@@ -136,9 +136,9 @@
 	char    name[16];
 #define VIDEO_SOUND_MONO	1
 #define VIDEO_SOUND_STEREO	2
-#define VIDEO_SOUND_LANG1	3
-#define VIDEO_SOUND_LANG2	4
-        __u16   mode;
+#define VIDEO_SOUND_LANG1	4
+#define VIDEO_SOUND_LANG2	8
+        __u16   mode;		/* detected audio carriers or one to set */
         __u16	balance;	/* Stereo balance */
         __u16	step;		/* Step actual volume uses */
 };
diff -u --recursive --new-file v2.1.131/linux/include/net/ax25.h linux/include/net/ax25.h
--- v2.1.131/linux/include/net/ax25.h	Fri Jul 31 17:07:28 1998
+++ linux/include/net/ax25.h	Tue Dec 22 10:46:09 1998
@@ -281,7 +281,7 @@
 extern void ax25_kick(ax25_cb *);
 extern void ax25_transmit_buffer(ax25_cb *, struct sk_buff *, int);
 extern void ax25_queue_xmit(struct sk_buff *);
-extern void ax25_check_iframes_acked(ax25_cb *, unsigned short);
+extern int  ax25_check_iframes_acked(ax25_cb *, unsigned short);
 
 /* ax25_route.c */
 extern void ax25_rt_device_down(struct device *);
diff -u --recursive --new-file v2.1.131/linux/include/net/br.h linux/include/net/br.h
--- v2.1.131/linux/include/net/br.h	Mon Apr  6 17:41:01 1998
+++ linux/include/net/br.h	Thu Dec 17 09:07:45 1998
@@ -293,6 +293,8 @@
 
 struct fdb *br_avl_find_addr(unsigned char addr[6]);
 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);
 
 /* externs */
 
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/crc.h linux/include/net/irda/crc.h
--- v2.1.131/linux/include/net/irda/crc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/crc.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,30 @@
+/*********************************************************************
+ *                
+ * Filename:      crc.h
+ * Version:       
+ * Description:   CRC routines
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Aug  4 20:40:53 1997
+ * Modified at:   Sat Dec 12 23:09:29 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ ********************************************************************/
+
+#ifndef IR_CRC_H
+#define IR_CRC_H
+
+#include <linux/types.h>
+
+#define INIT_FCS  0xffff   /* Initial FCS value */
+#define GOOD_FCS  0xf0b8   /* Good final FCS value */
+
+/* Recompute the FCS with one more character appended. */
+#define IR_FCS(fcs, byte) (((fcs)>>8)^irda_crc16_table[((fcs)^(byte)) & 0xff])
+
+/* Recompute the FCS with len bytes appended. */
+unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len);
+
+extern __u16 const irda_crc16_table[];
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/dongle.h linux/include/net/irda/dongle.h
--- v2.1.131/linux/include/net/irda/dongle.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/dongle.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,48 @@
+/*********************************************************************
+ *                
+ * Filename:      dongle.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Oct 21 22:47:12 1998
+ * Modified at:   Mon Dec 14 11:47:25 1998
+ * 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 DONGLE_H
+#define DONGLE_H
+
+#include <net/irda/qos.h>
+#include <net/irda/irda_device.h>
+
+/* These are the currently known dongles */
+typedef enum {
+	TEKRAM_DONGLE,
+	ESI_DONGLE,
+	ACTISYS_DONGLE,
+	ACTISYS_PLUS_DONGLE,
+} DONGLE_T;
+
+struct dongle {
+	DONGLE_T type;
+	void (*open)(struct irda_device *, int type);
+	void (*close)(struct irda_device *);
+	void (*reset)( struct irda_device *, int unused);
+	void (*change_speed)( struct irda_device *, int baudrate);
+	void (*qos_init)( struct irda_device *, struct qos_info *);
+};
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/ircomm_common.h linux/include/net/irda/ircomm_common.h
--- v2.1.131/linux/include/net/irda/ircomm_common.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/ircomm_common.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,233 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_common.h
+ * Version:       
+ * Description:   An implementation of IrCOMM service interface and state machine 
+ * Status:        Experimental.
+ * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
+ *
+ *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+/* #define DEBUG(n, args...) printk( KERN_DEBUG args) */ /* enable all debug message */
+
+#include <linux/types.h>
+#include <net/irda/irmod.h> 
+
+typedef enum {
+	COMM_DISCOVERY,
+        COMM_IDLE,
+	COMM_WAITI,
+	COMM_WAITR,
+	COMM_CONN,
+} IRCOMM_STATE;
+
+/* IrCOMM Events */
+typedef enum {
+	IRCOMM_CONNECT_REQUEST,
+	TTP_CONNECT_INDICATION,
+	LMP_CONNECT_INDICATION,
+
+	TTP_CONNECT_CONFIRM,
+	TTP_DISCONNECT_INDICATION,
+	LMP_CONNECT_CONFIRM,
+	LMP_DISCONNECT_INDICATION,
+
+	IRCOMM_CONNECT_RESPONSE,
+	IRCOMM_DISCONNECT_REQUEST,
+
+	TTP_DATA_INDICATION,
+	IRCOMM_DATA_REQUEST,
+	LMP_DATA_INDICATION,
+	IRCOMM_CONTROL_REQUEST,
+} IRCOMM_EVENT;
+
+
+#define IRCOMM_MAGIC            0x434f4d4d
+#define COMM_INIT_CTRL_PARAM    3          /* length of initial control parameters */
+#define COMM_CTRL_MIN           1          /* length of clen field */
+#define COMM_HEADER_SIZE        (LAP_HEADER+LMP_HEADER+TTP_HEADER+COMM_CTRL_MIN)
+#define COMM_DEFAULT_DATA_SIZE  64
+#define IRCOMM_MAX_CONNECTION   1          /* Don't change */
+
+#define IAS_PARAM               1
+#define CONTROL_CHANNEL         2
+
+
+
+#define UNKNOWN         0x00            /* not defined yet. */
+/* we use 9wire if servicetype=DEFAULT, but is it good? */
+#define DEFAULT         0x0a            /* private number */
+#define THREE_WIRE_RAW	0x01		/* bit 0 */
+#define THREE_WIRE	0x02		/* bit 1 */
+#define NINE_WIRE	0x04		/* bit 2 */
+#define CENTRONICS	0x08		/* bit 3 */
+
+#define SERIAL		0x01		/* bit 0 */
+#define PARALLEL	0x02		/* bit 1 */
+
+
+#define SERVICETYPE 0x00
+#define PORT_TYPE 0x02
+#define PORT_NAME 0x02
+#define FIXED_PORT_NAME 0x82
+
+#define DATA_RATE 0x10
+#define DATA_FORMAT 0x11
+#define FLOW_CONTROL 0x12
+#define XON_XOFF_CHAR 0x13
+#define ENQ_ACK_CHAR 0x14
+#define LINESTATUS 0x15
+#define BREAK_SIGNAL 0x16
+
+#define DTELINE_STATE 0x20
+#define DCELINE_STATE 0x21
+#define POLL_FOR_LINE_SETTINGS 0x22
+
+#define STATUS_QUERY 0x30
+#define SET_BUSY_TIMEOUT 0x31
+#define IEEE1284_MODE_SUPPORT 0x32
+#define IEEE1284_DEVICEID 0x33
+#define IEEE1284_MODE 0x34
+#define IEEE1284_ECP_EPP_DATA_TRANSFER 0x35
+
+#define TX_READY 0xFE  /* FIXME: this is not defined in IrCOMM spec */
+#define TX_BUSY  0XFF  /*         so we should find another way */
+
+
+/*  parameters of FLOW_CONTROL  */
+
+#define USE_RTS 0x08  /* use RTS on output */
+#define USE_CTS 0x04  /* use CTS on input */
+#define USE_DTR 0x20  /* use DTR on output */
+
+/*  parameters of DTELINE_STATE  */
+
+#define DELTA_DTR 0x01
+#define DELTA_RTS 0x02
+#define MCR_DTR 0x04
+#define MCR_RTS 0x08
+
+/*  parameters of DCELINE_STATE  */
+
+#define DELTA_CTS 0x01
+#define DELTA_DSR 0x02
+#define DELTA_RI  0x04 
+#define DELTA_DCD 0x08
+#define MSR_CTS   0x10
+#define MSR_DSR   0x20
+#define MSR_RI    0x40 
+#define MSR_DCD   0x80
+
+/*  parameters of DATA_FORMAT */
+
+#define LSR_OE     0x02    /* Overrun error indicator */
+#define LSR_PE     0x04    /* Parity error indicator */
+#define LSR_FE     0x08    /* Frame error indicator */
+#define LSR_BI     0x01    /* Break interrupt indicator */
+
+
+struct ircomm_cb{
+	int magic;
+	int state;          /* Current state of IrCOMM layer: 
+			     *  DISCOVERY,COMM_IDLE, COMM_WAITR,
+			     *  COMM_WAITI, COMM_CONN
+			     */
+	int in_use;
+	int null_modem_mode;     /* switch for null modem emulation */
+	int ttp_stop;
+	int max_txbuff_size;          
+	int maxsdusize;
+ 	__u32 daddr;        /* Device address of the peer device */ 
+
+	void (*d_handler)(struct ircomm_cb *self);
+	struct notify_t notify;     /* container of callbacks */
+
+	struct sk_buff *ctrl_skb;   /* queue of control channel */
+
+	struct tsap_cb *tsap;          /* IrTTP/LMP handle */
+	struct qos_info *qos;         /* Quality of Service */
+	
+	int reason;          /* I don't know about reason: 
+				see Irlmp.c or somewhere :p)*/ 
+
+	__u8 dlsap;          /* IrLMP dlsap */
+	__u8 lsap;           /* sap of local device */ 
+
+	__u8 pi ;            /* instruction of control channel*/ 
+	__u8 port_type;
+	__u8 peer_port_type;
+
+	__u8 servicetype;    
+	__u8 peer_servicetype;
+	__u8 data_format;   
+	__u8 peer_data_format;   
+	__u8 flow_ctrl;
+	__u8 peer_flow_ctrl;
+	__u8 line_status;
+	__u8 peer_line_status;
+	__u8 break_signal;
+	__u8 peer_break_signal;
+	__u8 dte;
+	__u8 peer_dte;
+	__u8 dce;
+	__u8 peer_dce;
+	__u8 xon_char;
+	__u8 xoff_char;
+	__u8 peer_xon_char;
+	__u8 peer_xoff_char;
+	__u8 enq_char;
+	__u8 ack_char;
+	__u8 peer_enq_char;
+	__u8 peer_ack_char;
+	__u8 busy_timeout;
+	__u8 peer_busy_timeout;
+	__u8 ecp_epp_mode;
+	__u8 peer_ecp_epp_mode;
+	__u8 channel_or_addr;
+	__u8 peer_channel_or_addr;
+	
+	__u32 data_rate;
+	__u32 peer_data_rate;
+	char port_name[60];
+
+};
+
+
+
+void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize);
+void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
+			     int maxsdusize);
+void ircomm_disconnect_request(struct ircomm_cb *self,
+				      struct sk_buff *userdata);
+void ircomm_data_request(struct ircomm_cb *self,
+			 struct sk_buff *userdata);
+void ircomm_control_request(struct ircomm_cb *self);
+void ircomm_append_ctrl(struct ircomm_cb *self, __u8 instruction);
+struct ircomm_cb *ircomm_attach_cable( __u8 servicetype, struct notify_t notify, 
+			 void *handler);
+int ircomm_detach_cable(struct ircomm_cb *self);
+
+
+void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb);
+void ircomm_accept_connect_confirm(void *instance, void *sap, struct qos_info *qos, 
+				   int maxsdusize, struct sk_buff *skb);
+void ircomm_accept_connect_indication(void *instance, void *sap,
+				      struct qos_info *qos, 
+				      int maxsdusize, struct sk_buff *skb);
+void ircomm_accept_disconnect_indication(void *instance, void *sap, LM_REASON reason,
+					 struct sk_buff *skb);
+void ircomm_accept_flow_indication(void *instance, void *sap, LOCAL_FLOW flow);
+void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
+
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.1.131/linux/include/net/irda/irda.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irda.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,153 @@
+/*********************************************************************
+ *                
+ * Filename:      irda.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Tue Dec  9 21:13:12 1997
+ * Modified at:   Mon Nov  2 14:49:11 1998
+ * 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 IRDA_H
+#define IRDA_H
+
+#include <linux/skbuff.h>
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE 
+#define FALSE 0
+#endif
+
+#define ALIGN __attribute__((aligned))
+#define PACK __attribute__((packed))
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 3
+static unsigned int net_debug = NET_DEBUG;
+
+#define DEBUG(n, args...) if (net_debug >= (n)) printk( KERN_DEBUG args)
+#define ASSERT(expr, func) \
+if(!(expr)) { \
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+        #expr,__FILE__,__FUNCTION__,__LINE__); \
+        ##func}
+#else
+#error
+#define DEBUG(n, args...)
+#define ASSERT(expr, func)
+#endif /* NET_DEBUG */
+
+#ifdef CHECK_SKB
+static unsigned int check_skb = CHECK_SKB;
+
+#define SK_FREED_SKB    0x0DE2C0DE
+#define SK_GOOD_SKB     0xDEC0DED1
+#define SK_HEAD_SKB     0x12231298
+
+extern int skb_check(struct sk_buff *skb,int,int, char *);
+
+#ifdef IS_SKB
+#undef IS_SKB
+#endif
+
+#define IS_SKB(skb, func) \
+if( skb_check((skb), 0, __LINE__,__FILE__) == -1) { \
+       ##func}
+
+#ifdef IS_SKB_HEAD
+#undef IS_SKB_HEAD
+#endif
+
+#define IS_SKB_HEAD(skb)  skb_check((skb), 1, __LINE__,__FILE__)
+
+#define ALLOC_SKB_MAGIC(skb) \
+if( check_skb) \
+        skb->magic_debug_cookie = SK_GOOD_SKB;
+
+#define FREE_SKB_MAGIC(skb) \
+if( check_skb) {\
+	skb->magic_debug_cookie = SK_FREED_SKB; \
+}
+
+#else
+#undef IS_SKB
+#define IS_SKB(skb, func)
+#undef IS_SKB_HEAD
+#define IS_SKB_HEAD(skb) 
+#define ALLOC_SKB_MAGIC(skb) 
+#define FREE_SKB_MAGIC(skb)
+#endif /* CHECK_SKB */
+
+/*
+ *  Magic numbers used by Linux/IR. Random numbers which must be unique to 
+ *  give the best protection
+ */
+#define IRTTY_MAGIC        0x2357
+#define LAP_MAGIC          0x1357
+#define LMP_MAGIC          0x4321
+#define LMP_LSAP_MAGIC     0x69333
+#define LMP_LAP_MAGIC      0x3432
+#define IRDA_DEVICE_MAGIC  0x63454
+#define IAS_MAGIC          0x007
+#define TTP_MAGIC          0x241169
+#define TTP_TSAP_MAGIC     0x4345
+#define IROBEX_MAGIC       0x341324
+#define HB_MAGIC           0x64534
+#define IRLAN_MAGIC        0x754
+#define IAS_OBJECT_MAGIC   0x34234
+#define IAS_ATTRIB_MAGIC   0x45232
+
+#define IAS_DEVICE_ID 0x5342
+#define IAS_PNP_ID    0xd342
+#define IAS_OBEX_ID   0x34323
+#define IAS_IRLAN_ID  0x34234
+#define IAS_IRCOMM_ID 0x2343
+#define IAS_IRLPT_ID  0x9876
+
+#endif /* IRDA_H */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.1.131/linux/include/net/irda/irda_device.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irda_device.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,152 @@
+/*********************************************************************
+ *                
+ * Filename:      irda_device.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Haris Zukanovic <haris@stud.cs.uit.no>
+ * Created at:    Tue Apr 14 12:41:42 1998
+ * Modified at:   Thu Dec 10 21:18:25 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Haris Zukanovic, <haris@stud.cs.uit.no>
+ *     Copyright (c) 1998 Dag Brattli, <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
+ *     All Rights Reserved.
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Haris Zukanovic 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 IRDA_DEVICE_H
+#define IRDA_DEVICE_H
+
+#include <linux/tty.h>
+#include <linux/netdevice.h>
+
+#include <net/irda/irda.h>
+#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
+
+#define IO_XMIT 0x01
+#define IO_RECV 0x02
+
+/* Chip specific info */
+struct chipio_t {
+        int iobase, iobase2;  /* IO base */
+        int io_ext, io_ext2;  /* Length of iobase */
+        int irq, irq2;        /* Interrupts used */
+        int fifo_size;        /* FIFO size */
+
+        int dma, dma2;        /* DMA channel used */
+        int irqflags;         /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */
+	int direction;        /* Used by some FIR drivers */
+
+	int baudrate;         /* Currently used baudrate */
+	int dongle_id;        /* Dongle or transceiver currently used */
+};
+
+/* Buffer specific info */
+struct iobuff_t {
+	int state;            /* Receiving state (transmit state not used) */
+	int in_frame;         /* True if receiving frame */
+
+	__u8 *data;	      /* the buffer */
+	__u8 *head;	      /* start of data in buffer */
+	__u8 *tail;           /* end of data in buffer */
+
+	int offset;	      /* Usually data + offset = head */
+	int len;	      /* currently used bytes in buffer */
+	int truesize;	      /* total size of the data area */
+	__u16 fcs;
+
+	int flags;            /* Allocation flags (GFP_KERNEL | GFP_DMA ) */
+};
+
+/* 
+ * This structure contains data that _we_ would have liked to be in the device
+ * structure, but we don't want to mess it up more than it is already. Better 
+ * to keep the data in separate structures! This structure abstracts common 
+ * stuff from IrDA port implementations.
+ */
+struct irda_device {
+	QUEUE q; /* Must be first */
+
+        int  magic;	/* our magic bullet */
+	char name[16];
+
+	struct irlap_cb *irlap; /* The link layer we are connected to  */
+	struct device netdev;   /* Yes! we are some kind of netdevice */
+	struct enet_statistics stats;
+
+/* 	int flags; */
+
+ 	void *priv;           /* Pointer to low level implementation */
+
+	struct qos_info qos;  /* QoS capabilities for this device */
+
+	struct chipio_t io;
+	struct iobuff_t tx_buff;
+	struct iobuff_t rx_buff;
+
+	int media_busy;
+	
+	/* Media busy stuff */
+	struct timer_list media_busy_timer;
+	struct timer_list todo_timer;
+
+	int  (*hard_xmit)( struct sk_buff *skb, struct device *dev);
+        void (*change_speed)( struct irda_device *driver, int baud);
+
+ 	int (*is_receiving)(struct irda_device *);     /* receiving? */
+	/* int (*is_tbusy)(struct irda_device *); */   /* transmitting? */
+	void (*wait_until_sent)(struct irda_device *);
+
+	int new_speed; /* Will be removed in future */
+};
+
+extern hashbin_t *irda_device;
+
+/* Function prototypes */
+int  irda_device_init( void);
+void irda_device_cleanup( void);
+
+int  irda_device_open( struct irda_device *, char *name, void *priv);
+void irda_device_close( struct irda_device *);
+
+/* Interface to be uses by IrLAP */
+inline void irda_device_set_media_busy( struct irda_device *, int status);
+inline int  irda_device_is_media_busy( struct irda_device *);
+inline int  irda_device_is_receiving( struct irda_device *);
+inline void irda_device_change_speed( struct irda_device *, int);
+
+inline struct qos_info *irda_device_get_qos( struct irda_device *self);
+int irda_device_txqueue_empty( struct irda_device *self);
+
+int irda_device_setup( struct device *dev);
+
+__inline__ int irda_get_mtt( struct sk_buff *skb);
+
+void setup_dma( int channel, char *buffer, int count, int mode);
+
+#endif
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irdacall.h linux/include/net/irda/irdacall.h
--- v2.1.131/linux/include/net/irda/irdacall.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irdacall.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,2 @@
+/* Separate to keep compilation of protocols.c simpler */
+extern void irda_proto_init(struct net_proto *pro);
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/iriap.h linux/include/net/irda/iriap.h
--- v2.1.131/linux/include/net/irda/iriap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/iriap.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,123 @@
+/*********************************************************************
+ *                
+ * Filename:      iriap.h
+ * Version:       
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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 IRIAP_H
+#define IRIAP_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include <net/irda/qos.h>
+#include <net/irda/iriap_event.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/irqueue.h>
+#include <net/irda/timer.h>
+
+#define LST 0x80
+#define ACK 0x40
+
+#define IAS_SERVER 0
+#define IAS_CLIENT 1
+
+/* IrIAP Op-codes */
+#define GET_INFO_BASE      0x01
+#define GET_OBJECTS        0x02
+#define GET_VALUE          0x03
+#define GET_VALUE_BY_CLASS 0x04
+#define GET_OBJECT_INFO    0x05
+#define GET_ATTRIB_NAMES   0x06
+
+#define IAS_SUCCESS        0
+#define IAS_CLASS_UNKNOWN  1
+#define IAS_ATTRIB_UNKNOWN 2
+
+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        daddr;
+	__u8         operation;
+
+	struct sk_buff *skb;
+	struct lsap_cb *lsap;
+	__u8 slsap_sel;
+
+	/* Client states */
+	IRIAP_STATE client_state;
+	IRIAP_STATE call_state;
+	
+	/* Server states */
+	IRIAP_STATE server_state;
+	IRIAP_STATE r_connect_state;
+	
+	CONFIRM_CALLBACK confirm;
+	void *priv;
+
+	struct timer_list watchdog_timer;
+};
+
+int  iriap_init(void);
+void iriap_cleanup(void);
+void iriap_getvaluebyclass_request( __u32 addr, char *name, char *attr, 
+				    CONFIRM_CALLBACK callback, void *priv);
+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);
+void iriap_connect_confirm( void *instance, void *sap, struct qos_info *qos, 
+			    int max_sdu_size, struct sk_buff *skb);
+void iriap_connect_indication( void *instance, void *sap, 
+			       struct qos_info *qos, int max_sdu_size,
+			       struct sk_buff *skb);
+void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb);
+
+void iriap_register_server(void);
+
+void iriap_watchdog_timer_expired( unsigned long data);
+
+static inline void iriap_start_watchdog_timer( struct iriap_cb *self, 
+					       int timeout) 
+{
+	irda_start_timer( &self->watchdog_timer, timeout, 
+			  (unsigned long) self, iriap_watchdog_timer_expired);
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/iriap_event.h linux/include/net/irda/iriap_event.h
--- v2.1.131/linux/include/net/irda/iriap_event.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/iriap_event.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,84 @@
+/*********************************************************************
+ *                
+ * Filename:      iriap_event.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Aug  4 20:40:53 1997
+ * Modified at:   Fri Sep  4 13:19:28 1998
+ * Modified 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 IRIAP_FSM_H
+#define IRIAP_FSM_H
+
+/* Forward because of circular include dependecies */
+struct iriap_cb;
+
+/* IrIAP states */
+typedef enum {
+	/* Client */
+	S_DISCONNECT,
+	S_CONNECTING,
+	S_CALL,
+
+	/* S-Call */
+	S_MAKE_CALL,
+	S_CALLING,
+	S_OUTSTANDING,
+	S_REPLYING,
+	S_WAIT_FOR_CALL,
+	S_WAIT_ACTIVE,
+
+	/* Server */
+	R_DISCONNECT,
+	R_CALL,
+	
+	/* R-Connect */
+	R_WAITING,
+	R_WAIT_ACTIVE,
+	R_RECEIVING,
+	R_EXECUTE,
+	R_RETURNING,
+} IRIAP_STATE;
+
+typedef enum {
+	IAP_CALL_REQUEST,
+	IAP_CALL_REQUEST_GVBC,
+	IAP_CALL_RESPONSE,
+	IAP_RECV_F_LST,
+	IAP_LM_DISCONNECT_INDICATION,
+	IAP_LM_CONNECT_INDICATION,
+	IAP_LM_CONNECT_CONFIRM,
+} IRIAP_EVENT;
+
+void iriap_next_client_state   ( struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_call_state     ( struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_server_state   ( struct iriap_cb *self, IRIAP_STATE state);
+void iriap_next_r_connect_state( struct iriap_cb *self, IRIAP_STATE state);
+
+
+void iriap_do_client_event( struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb);
+void iriap_do_call_event  ( struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb);
+
+void iriap_do_server_event   ( struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb);
+void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irias_object.h linux/include/net/irda/irias_object.h
--- v2.1.131/linux/include/net/irda/irias_object.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irias_object.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,107 @@
+/*********************************************************************
+ *                
+ * Filename:      irias_object.h
+ * Version:       
+ * Description:   
+ * 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 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 LM_IAS_OBJECT_H
+#define LM_IAS_OBJECT_H
+
+#include "irqueue.h"
+
+/* LM-IAS Attribute types */
+#define IAS_MISSING 0
+#define IAS_INTEGER 1
+#define IAS_OCT_SEQ 2
+#define IAS_STRING  3
+
+/*
+ *  LM-IAS Object
+ */
+struct ias_object {
+	QUEUE queue;     /* Must be first! */
+
+	int magic;
+	
+	char  *name;
+	int   id;
+
+	hashbin_t *attribs;
+};
+
+/*
+ *  Values used by LM-IAS attributes
+ */
+struct ias_value {
+	/* Value description */
+        __u8    type;
+	int     charset; /* Only used by string type */
+        int     len;
+	
+	/* Value */
+	union {
+		int integer;
+		char *string;
+		__u8 *oct_seq;
+	} t;
+};
+
+/*
+ *  Attributes used by LM-IAS objects
+ */
+struct ias_attrib {
+	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 *strdup( char *str);
+
+struct ias_object *irias_new_object( char *name, int id);
+void irias_insert_object( struct ias_object *obj);
+void __irias_delete_object( struct ias_object *obj);
+void irias_delete_object( char *name);
+
+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);
+struct ias_object *irias_find_object( char *name);
+struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name);
+
+struct ias_value *irias_new_string_value( char *string);
+struct ias_value *irias_new_integer_value( int integer);
+struct ias_value *irias_new_octseq_value( __u8 *octseq , int len);
+void irias_delete_value( struct ias_value *value);
+
+extern struct ias_value missing;
+extern hashbin_t *objects;
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlan_cli.h linux/include/net/irda/irlan_cli.h
--- v2.1.131/linux/include/net/irda/irlan_cli.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_cli.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,65 @@
+/*********************************************************************
+ *                
+ * 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.1.131/linux/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h
--- v2.1.131/linux/include/net/irda/irlan_common.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_common.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,199 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan.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:   Thu Oct 29 13:23:11 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_H
+#define IRLAN_H
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+
+#include "irqueue.h"
+#include "irttp.h"
+
+#define IRLAN_MTU 1518
+
+/* Command packet types */
+#define CMD_GET_PROVIDER_INFO   0
+#define CMD_GET_MEDIA_CHAR      1
+#define CMD_OPEN_DATA_CHANNEL   2
+#define CMD_CLOSE_DATA_CHAN     3
+#define CMD_RECONNECT_DATA_CHAN 4
+#define CMD_FILTER_OPERATION    5
+
+/* Some responses */
+#define RSP_SUCCESS                 0
+#define RSP_INSUFFICIENT_RESOURCES  1
+#define RSP_INVALID_COMMAND_FORMAT  2
+#define RSP_COMMAND_NOT_SUPPORTED   3
+#define RSP_PARAM_NOT_SUPPORTED     4
+#define RSP_VALUE_NOT_SUPPORTED     5
+#define RSP_NOT_OPEN                6
+#define RSP_AUTHENTICATION_REQUIRED 7
+#define RSP_INVALID_PASSWORD        8
+#define RSP_PROTOCOL_ERROR          9
+#define RSP_ASYNCHRONOUS_ERROR    255
+
+/* Media types */
+#define MEDIA_802_3 1
+#define MEDIA_802_5 2
+
+/* Filter parameters */
+#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
+
+/* Filter modes */
+#define ALL    1
+#define FILTER 2
+#define NONE   3
+
+/* Filter operations */
+#define GET     1
+#define CLEAR   2
+#define ADD     3
+#define REMOVE  4
+#define DYNAMIC 5
+
+/* Access types */
+#define DIRECT 1
+#define PEER   2
+#define HOSTED 3
+
+#define IRLAN_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+
+/*
+ *  IrLAN client subclass
+ */
+struct irlan_client_cb {
+	/*
+	 *  Client fields
+	 */
+	int open_retries;
+	
+	__u8 reconnect_key[255];
+	__u8 key_len;
+	
+	int unicast_open;
+	int broadcast_open;
+};
+
+/*
+ * IrLAN servers subclass
+ */
+struct irlan_server_cb {
+	
+	/*
+	 *  Store some values here which are used by the irlan_server to parse
+	 *  FILTER_OPERATIONs
+	 */
+	int data_chan;
+	int filter_type;
+	int filter_mode;
+	int filter_operation;
+	int filter_entry;
+
+	__u8 mac_address[6]; /* Generated MAC address for peer device */
+};
+
+/*
+ *  IrLAN super class
+ */
+struct irlan_cb {
+	QUEUE queue; /* Must be first */
+
+	int    magic;
+	char   ifname[9];
+	struct device dev;  /* Ethernet device structure*/
+	struct enet_statistics stats;
+
+	__u32 saddr;        /* Source devcie address */
+	__u32 daddr;        /* Destination device address */
+	int   connected;    /* TTP layer ready to exchange ether frames */
+	
+	int state;  /* Current state of IrLAN layer */
+
+	int media;	
+	
+	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_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_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);
+
+int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len);
+void print_ret_code( __u8 code);
+
+extern hashbin_t *irlan;
+
+#endif
+
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlan_eth.h linux/include/net/irda/irlan_eth.h
--- v2.1.131/linux/include/net/irda/irlan_eth.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_eth.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,40 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_eth.h
+ * Version:       
+ * Description:   
+ * 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 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_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_flow_indication( void *instance, void *sap, LOCAL_FLOW flow);
+
+void irlan_eth_set_multicast_list( struct device *dev);
+struct enet_statistics *irlan_eth_get_stats(struct device *dev);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlan_event.h linux/include/net/irda/irlan_event.h
--- v2.1.131/linux/include/net/irda/irlan_event.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_event.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,86 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_event.h
+ * Version:       
+ * Description:   LAN access
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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_EVENT_H
+#define IRLAN_EVENT_H
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+#include <net/irda/irlan_common.h>
+
+typedef enum {
+	IRLAN_IDLE,
+	IRLAN_QUERY,
+	IRLAN_CONN, 
+	IRLAN_INFO,
+	IRLAN_MEDIA,
+	IRLAN_OPEN,
+	IRLAN_WAIT,
+	IRLAN_ARB, 
+	IRLAN_DATA,
+	IRLAN_CLOSE,
+	IRLAN_SYNC
+} IRLAN_STATE;
+
+/* IrLAN Client Events */
+typedef enum {
+	IRLAN_DISCOVERY_INDICATION,
+	IRLAN_IAS_PROVIDER_AVAIL,
+	IRLAN_IAS_PROVIDER_NOT_AVAIL,
+	IRLAN_LAP_DISCONNECT,
+	IRLAN_LMP_DISCONNECT,
+	IRLAN_CONNECT_COMPLETE,
+	IRLAN_DATA_INDICATION,
+	IRLAN_DATA_CONNECT_INDICATION,
+	IRLAN_RETRY_CONNECT,
+
+	IRLAN_CONNECT_INDICATION,
+	IRLAN_GET_INFO_CMD,
+	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;
+};
+
+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_next_state( struct irlan_cb *self, 
+		       IRLAN_STATE state);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlan_srv.h linux/include/net/irda/irlan_srv.h
--- v2.1.131/linux/include/net/irda/irlan_srv.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlan_srv.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,62 @@
+/*********************************************************************
+ *                
+ * 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.1.131/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.1.131/linux/include/net/irda/irlap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlap.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,232 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap.h
+ * Version:       0.3
+ * 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 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 IRLAP_H
+#define IRLAP_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ppp_defs.h>
+#include <linux/ppp-comp.h>
+
+#include <net/irda/irlap_event.h>
+
+#define LAP_RELIABLE   1
+#define LAP_UNRELIABLE 0
+
+#define LAP_ADDR_HEADER 1  /* IrLAP Address Header */
+#define LAP_CTRL_HEADER 1  /* IrLAP Control Header */
+#define LAP_COMP_HEADER 1  /* IrLAP Compression Header */
+
+#ifdef CONFIG_IRDA_COMPRESSION
+#  define LAP_HEADER  (LAP_ADDR_HEADER + LAP_CTRL_HEADER + LAP_COMP_HEADER)
+#  define IRDA_COMPRESSED 1
+#  define IRDA_NORMAL     0
+#else
+#define LAP_HEADER (LAP_ADDR_HEADER + LAP_CTRL_HEADER)
+#endif
+
+#define BROADCAST  0xffffffff /* Broadcast device address */
+#define CBROADCAST 0xfe       /* Connection broadcast address */
+#define XID_FORMAT 0x01       /* Discovery XID format */
+
+#define LAP_WINDOW_SIZE 8
+#define MAX_CONNECTIONS 1
+
+#define NR_EXPECTED     1
+#define NR_UNEXPECTED   0
+#define NR_INVALID     -1
+
+#define NS_EXPECTED     1
+#define NS_UNEXPECTED   0
+#define NS_INVALID     -1
+
+#ifdef CONFIG_IRDA_COMPRESSION
+/*  
+ *  Just some shortcuts (may give you strange compiler errors if you change 
+ *  them :-)
+ */
+#define irda_compress    (*self->compessor.cp->compress)
+#define irda_comp_free   (*self->compressor.cp->comp_free)
+#define irda_decompress  (*self->decompressor.cp->decompress)
+#define irda_decomp_free (*self->decompressor.cp->decomp_free)
+#define irda_incomp      (*self->decompressor.cp->incomp)
+
+struct irda_compressor {
+	QUEUE queue;
+
+	struct compressor *cp;
+	void *state; /* Not used by IrDA */
+};
+#endif
+
+/* Main structure of IrLAP */
+struct irlap_cb {
+	QUEUE q; /* Must be first */
+
+	int magic;
+
+	struct irda_device *irdev;
+	struct device      *netdev;
+
+	/* Connection state */
+	volatile IRLAP_STATE state;       /* Current state */
+
+	/* Timers used by IrLAP */
+	struct timer_list query_timer;
+	struct timer_list slot_timer;
+	struct timer_list discovery_timer;
+	struct timer_list final_timer;
+	struct timer_list poll_timer;
+	struct timer_list wd_timer;
+	struct timer_list backoff_timer;
+
+	/* Timeouts which will be different with different turn time */
+	int poll_timeout;
+	int final_timeout;
+	int wd_timeout;
+
+	struct sk_buff_head tx_list;  /* Frames to be transmitted */
+
+ 	__u8    caddr;        /* Connection address */
+	__u32   saddr;        /* Source device address */
+	__u32   daddr;        /* Destination device address */
+
+	int     retry_count;  /* Times tried to establish connection */
+	int     add_wait;     /* True if we are waiting for frame */
+
+#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 */
+
+	int     local_busy;
+	int     remote_busy;
+	int     xmitflag;
+
+	__u8    vs;           /* Next frame to be sent */
+	__u8    vr;           /* Next frame to be received */
+	int     tmp;
+	__u8    va;           /* Last frame acked */
+ 	int     window;       /* Nr of I-frames allowed to send */
+	int     window_size;  /* Current negotiated window size */
+	int     window_bytes; /* Number of bytes allowed to send */
+	int     bytes_left;   /* Number of bytes allowed to transmit */
+
+	struct sk_buff_head wx_list;
+
+	__u8    ack_required;
+	
+	/* XID parameters */
+ 	__u8    S;           /* Number of slots */
+	__u8    slot;        /* Random chosen slot */
+ 	__u8    s;           /* Current slot */
+	int     frame_sent;  /* Have we sent reply? */
+
+	int discovery_count;
+	hashbin_t *discovery_log;
+ 	DISCOVERY *discovery_cmd;
+
+	struct qos_info qos_tx;    /* QoS requested by peer */
+	struct qos_info qos_rx;    /* QoS requested by self */
+
+	struct notify_t notify; /* Callbacks to IrLMP */
+
+	int     mtt_required;  /* Minumum turnaround time required */
+	int     xbofs_delay;   /* Nr of XBOF's used to MTT */
+	int     bofs_count;    /* Negotiated extra BOFs */
+
+ 	struct irda_statistics stats;
+
+#ifdef CONFIG_IRDA_RECYCLE_RR
+	struct sk_buff *recycle_rr_skb;
+#endif
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	struct irda_compressor compressor;
+        struct irda_compressor decompressor;
+#endif
+};
+
+extern hashbin_t *irlap;
+
+/* 
+ *  Function prototypes 
+ */
+
+int irlap_init( void);
+void irlap_cleanup( void);
+
+struct irlap_cb *irlap_open( struct irda_device *dev);
+void irlap_close( struct irlap_cb *self);
+
+void irlap_connect_request( struct irlap_cb *self, __u32 daddr, 
+			    struct qos_info *qos, int sniff);
+void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb);
+void irlap_connect_confirm( struct irlap_cb *, struct sk_buff *skb);
+
+inline void irlap_data_indication( struct irlap_cb *, struct sk_buff *);
+inline void irlap_unit_data_indication( struct irlap_cb *, struct sk_buff *);
+inline void irlap_data_request( struct irlap_cb *, struct sk_buff *, 
+				int reliable);
+
+void irlap_disconnect_request( struct irlap_cb *);
+void irlap_disconnect_indication( struct irlap_cb *, LAP_REASON reason);
+
+void irlap_status_indication( int quality_of_link);
+
+void irlap_test_request( __u8 *info, int len);
+
+void irlap_discovery_request( struct irlap_cb *, DISCOVERY *discovery);
+void irlap_discovery_confirm( struct irlap_cb *, hashbin_t *discovery_log);
+void irlap_discovery_indication( struct irlap_cb *, DISCOVERY *discovery);
+
+void irlap_reset_indication( struct irlap_cb *self);
+void irlap_reset_confirm(void);
+
+void irlap_update_nr_received( struct irlap_cb *, int nr);
+int irlap_validate_nr_received( struct irlap_cb *, int nr);
+int irlap_validate_ns_received( struct irlap_cb *, int ns);
+
+int  irlap_generate_rand_time_slot( int S, int s);
+void irlap_initiate_connection_state( struct irlap_cb *);
+void irlap_flush_all_queues( struct irlap_cb *);
+void irlap_change_speed( struct irlap_cb *, int);
+void irlap_wait_min_turn_around( struct irlap_cb *, struct qos_info *);
+
+void irlap_init_qos_capabilities( struct irlap_cb *, struct qos_info *);
+void irlap_apply_default_connection_parameters( struct irlap_cb *self);
+void irlap_apply_connection_parameters( struct irlap_cb *, struct qos_info *);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlap_comp.h linux/include/net/irda/irlap_comp.h
--- v2.1.131/linux/include/net/irda/irlap_comp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlap_comp.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,47 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap_comp.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Oct  9 09:21:12 1998
+ * Modified at:   Sat Dec 12 12:23:16 1998
+ * 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 IRLAP_COMP_H
+#define IRLAP_COMP_H
+
+#include <linux/ppp-comp.h>
+
+#define CI_BZIP2  27 /* Random pick */
+
+extern hashbin_t *irlap_compressors;
+
+int irda_register_compressor( struct compressor *cp);
+void irda_unregister_compressor( struct compressor *cp);
+
+int irda_set_compression( struct irlap_cb *self, int proto);
+void irlap_compressor_init( struct irlap_cb *self, int compress);
+void irda_free_compression( struct irlap_cb *self);
+
+struct sk_buff *irlap_compress_frame( struct irlap_cb *self, 
+				      struct sk_buff *skb);
+struct sk_buff *irlap_decompress_frame( struct irlap_cb *self, 
+					struct sk_buff *skb);
+
+#endif
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlap_event.h linux/include/net/irda/irlap_event.h
--- v2.1.131/linux/include/net/irda/irlap_event.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlap_event.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,119 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap_event.h
+ * Version:       0.1
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Aug 16 00:59:29 1997
+ * Modified at:   Mon Dec 14 13:58:27 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 IRLAP_EVENT_H
+#define IRLAP_EVENT_H
+
+#include "irmod.h"
+
+struct irlap_cb;
+
+/* IrLAP States */
+typedef enum {
+	LAP_NDM,         /* Normal disconnected mode */
+	LAP_QUERY,
+	LAP_REPLY,
+	LAP_CONN,        /* Connect indication */
+	LAP_SETUP,       /* Setting up connection */
+	LAP_OFFLINE,     /* A really boring state */
+	LAP_XMIT_P,
+	LAP_PCLOSE,
+	LAP_NRM_P,       /* Normal response mode as primary */
+	LAP_RESET_WAIT,
+	LAP_RESET,
+	LAP_NRM_S,       /* Normal response mode as secondary */
+	LAP_XMIT_S,
+	LAP_SCLOSE,
+} IRLAP_STATE;
+
+/* IrLAP Events */
+typedef enum {
+	/* Services events */
+	DISCOVERY_REQUEST,
+	CONNECT_REQUEST,
+	CONNECT_RESPONSE,
+	DISCONNECT_REQUEST,
+	DATA_REQUEST,
+	RESET_REQUEST,
+
+	/* Send events */
+	SEND_I_CMD,
+
+	/* Receive events */
+	RECV_DISCOVERY_XID_CMD,
+	RECV_DISCOVERY_XID_RSP,
+	RECV_SNRM_CMD,
+	RECV_TEST_CMD,
+	RECV_UA_RSP,
+	RECV_DM_RSP,
+	RECV_I_CMD,
+	RECV_I_RSP,
+	RECV_UI_FRAME,
+	RECV_FRMR_RSP,
+	RECV_RR_CMD,
+	RECV_RR_RSP,
+	RECV_RNR_FRAME,
+	RECV_DISC_FRAME,
+
+	/* Timer events */
+	SLOT_TIMER_EXPIRED,
+	QUERY_TIMER_EXPIRED,
+	FINAL_TIMER_EXPIRED,
+	POLL_TIMER_EXPIRED,
+	DISCOVERY_TIMER_EXPIRED,
+	WD_TIMER_EXPIRED,
+	BACKOFF_TIMER_EXPIRED,
+} IRLAP_EVENT;
+
+/*
+ *  Various things used by the IrLAP state machine
+ */
+struct irlap_info {
+	__u8 caddr;   /* Connection address */
+	__u8 control; /* Frame type */
+        __u8 cmd;
+
+	__u32 saddr;
+	__u32 daddr;
+	
+	int pf;        /* Poll/final bit set */
+
+	__u8  nr;      /* Sequence number of next frame expected */
+	__u8  ns;      /* Sequence number of frame sent */
+
+	int  S;        /* Number of slots */
+	int  slot;     /* Random chosen slot */
+	int  s;        /* Current slot */
+
+	DISCOVERY *discovery; /* Discovery information */
+};
+
+extern char *irlap_state[];
+
+void irlap_do_event( struct irlap_cb *self, IRLAP_EVENT event, 
+		     struct sk_buff *skb, struct irlap_info *info);
+void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state);
+void irlap_print_event( IRLAP_EVENT event);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h
--- v2.1.131/linux/include/net/irda/irlap_frame.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlap_frame.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,155 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap_frame.h
+ * Version:       0.3
+ * 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:   Mon Dec 14 14:22:23 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 IRLAP_FRAME_H
+#define IRLAP_FRAME_H
+
+#include <linux/skbuff.h>
+
+#include <net/irda/irmod.h>
+#include <net/irda/irlap.h>
+#include <net/irda/qos.h>
+
+/* Frame types and templates */
+#define INVALID   0xff
+
+/* Unnumbered (U) commands */
+#define SNRM_CMD  0x83 /* Set Normal Response Mode */
+#define DISC_CMD  0x43 /* Disconnect */
+#define XID_CMD   0x2f /* Exchange Station Identification */
+#define TEST_CMD  0xe3 /* Test */
+
+/* Unnumbered responses */
+#define RNRM_RSP  0x83 /* Request Normal Response Mode */
+#define UA_RSP    0x63 /* Unnumbered Acknowledgement */
+#define FRMR_RSP  0x87 /* Frame Reject */
+#define DM_RSP    0x0f /* Disconnect Mode */
+#define RD_RSP    0x43 /* Request Disconnection */
+#define XID_RSP   0xaf /* Exchange Station Identification */
+#define TEST_RSP  0xe3 /* Test frame */
+
+/* Supervisory (S) */
+#define RR        0x01 /* Receive Ready */
+#define REJ       0x09 /* Reject */
+#define RNR       0x05 /* Receive Not Ready */
+#define SREJ      0x0d /* Selective Reject */
+
+/* Information (I) */
+#define I_FRAME   0x00 /* Information Format */
+#define UI_FRAME  0x03 /* Unnumbered Information */
+
+#define CMD_FRAME  0x01
+#define RSP_FRAME  0x00
+
+#define PF_BIT 0x10 /* Poll/final bit */
+
+#define IR_S                  0x01    /* Supervisory frames */
+#define IR_RR                 0x01    /* Receiver ready */
+#define IR_RNR                0x05    /* Receiver not ready */
+#define IR_REJ                0x09    /* Reject */
+#define IR_U                  0x03    /* Unnumbered frames */
+#define IR_SNRM               0x2f    /* Set Asynchronous Balanced Mode */
+
+#define IR_DISC               0x43    /* Disconnect */
+#define IR_DM                 0x0f    /* Disconnected mode */
+#define IR_UA                 0x63    /* Unnumbered acknowledge */
+#define IR_FRMR               0x87    /* Frame reject */
+#define IR_UI                 0x03    /* Unnumbered information */
+
+struct xid_frame {
+	__u8  caddr     __attribute__((packed)); /* Connection address */
+	__u8  control   __attribute__((packed));
+	__u8  ident     __attribute__((packed)); /* Should always be XID_FORMAT */ 
+	__u32 saddr     __attribute__((packed)); /* Source device address */
+	__u32 daddr     __attribute__((packed)); /* Destination device address */
+	__u8  flags     __attribute__((packed)); /* Discovery flags */
+	__u8  slotnr    __attribute__((packed));
+	__u8  version   __attribute__((packed));
+	__u8  discovery_info[0]  __attribute__((packed));
+};
+
+struct test_frame {
+	__u8 caddr;          /* Connection address */
+	__u8 control;
+	__u8 saddr;          /* Source device address */
+	__u8 daddr;          /* Destination device address */
+	__u8 *info;          /* Information */
+};
+
+struct ua_frame {
+	__u8 caddr   __attribute__((packed));
+	__u8 control __attribute__((packed));
+
+	__u32 saddr     __attribute__((packed)); /* Source device address */
+	__u32 daddr     __attribute__((packed)); /* Dest device address */
+	__u8  params[0];
+};
+	
+struct i_frame {
+	__u8 caddr   __attribute__((packed));
+	__u8 control __attribute__((packed));
+	__u8 data[0] __attribute__((packed));
+};
+
+struct snrm_frame {
+	__u8  caddr   __attribute__((packed));
+	__u8  control __attribute__((packed));
+	__u32 saddr   __attribute__((packed));
+	__u32 daddr   __attribute__((packed));
+	__u8  ncaddr  __attribute__((packed));
+	__u8  params[0];
+};
+
+/* Per-packet information we need to hide inside sk_buff */
+struct irlap_skb_cb {
+	int mtt;   /* minimum turn around time */
+	int xbofs; /* number of xbofs required */
+	int vs;    /* next frame to send */
+	int vr;    /* next frame to receive */
+};
+
+__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb);
+
+void irlap_send_discovery_xid_frame( struct irlap_cb *, int S, __u8 s, 
+				     __u8 command, DISCOVERY *discovery);
+void irlap_send_snrm_frame( struct irlap_cb *, struct qos_info *);
+void irlap_send_ua_response_frame( struct irlap_cb *, struct qos_info *);
+void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb,
+			  int command);
+void irlap_send_dm_frame( struct irlap_cb *);
+void irlap_send_disc_frame( struct irlap_cb *);
+void irlap_send_rr_frame( struct irlap_cb *, int command);
+
+void irlap_send_data_primary( struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_primary_poll( struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary( struct irlap_cb *, struct sk_buff *);
+void irlap_send_data_secondary_final( struct irlap_cb *, struct sk_buff *);
+void irlap_resend_rejected_frames( struct irlap_cb *, int command);
+
+void irlap_send_i_frame( struct irlap_cb *, struct sk_buff *, int command);
+void irlap_send_ui_frame( struct irlap_cb *, struct sk_buff *, int command);
+
+/* void irlap_input( struct irlap_cb *self, struct sk_buff *skb); */
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h
--- v2.1.131/linux/include/net/irda/irlmp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlmp.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,239 @@
+/*********************************************************************
+ *                
+ * Filename:      irlmp.h
+ * Version:       0.3
+ * Description:   IrDA Link Management Protocol (LMP) layer
+ * 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 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 IRLMP_H
+#define IRLMP_H
+
+#include <linux/config.h>
+#include <linux/types.h>
+
+#include "irmod.h"
+#include "qos.h"
+#include "irlap.h"
+#include "irlmp_event.h"
+#include "irqueue.h"
+
+/* LSAP-SEL's */
+#define LSAP_MASK     0x7f
+#define LSAP_IAS      0x00
+#define LSAP_ANY      0xff
+
+/* Predefined LSAPs used by the various servers */
+#define TSAP_IRLAN    0x05
+#define LSAP_IRLPT    0x06
+#define TSAP_IROBEX   0x07
+#define TSAP_IRCOMM   0x08
+
+#define LMP_HEADER          2    /* Dest LSAP + Source LSAP */
+#define LMP_CONTROL_HEADER  4
+#define LMP_MAX_HEADER      (LAP_HEADER+LMP_HEADER)
+
+#define LM_MAX_CONNECTIONS  10
+
+/* Hint bit positions for first hint byte */
+#define HINT_PNP         0x01
+#define HINT_PDA         0x02
+#define HINT_COMPUTER    0x04
+#define HINT_PRINTER     0x08
+#define HINT_MODEM       0x10
+#define HINT_FAX         0x20
+#define HINT_LAN         0x40
+#define HINT_EXTENSION   0x80
+
+/* Hint bit positions for second hint byte (first extension byte) */
+#define HINT_TELEPHONY   0x01
+#define HINT_FILE_SERVER 0x02
+#define HINT_COMM        0x04
+#define HINT_MESSAGE     0x08
+#define HINT_HTTP        0x10
+#define HINT_OBEX        0x20
+
+typedef enum {
+	S_PNP,
+	S_PDA,
+	S_COMPUTER,
+	S_PRINTER,
+	S_MODEM,
+	S_FAX,
+	S_LAN,
+	S_TELEPHONY,
+	S_COMM,
+	S_OBEX,
+} SERVICE;
+
+#define S_END 0xff
+
+#define CLIENT 1
+#define SERVER 2
+
+typedef void (*DISCOVERY_CALLBACK) ( DISCOVERY*);
+
+struct irlmp_registration {
+	QUEUE queue; /* Must be first */
+
+	int service; /* LAN, OBEX, COMM etc. */
+	int type;    /* Client or server or both */
+
+	DISCOVERY_CALLBACK discovery_callback;
+};
+
+struct lap_cb; /* Forward decl. */
+
+/*
+ *  Information about each logical LSAP connection
+ */
+struct lsap_cb {
+	QUEUE queue;      /* Must be first */
+
+	int   magic;
+
+	int   connected;
+	int   persistent;
+
+	struct irda_statistics stats;
+
+	__u8  slsap_sel;   /* Source (this) LSAP address */
+	__u8  dlsap_sel;   /* Destination LSAP address (if connected) */
+
+	struct sk_buff *tmp_skb; /* Store skb here while connecting */
+
+	struct timer_list watchdog_timer;
+
+	IRLMP_STATE     lsap_state;  /* Connection state */
+	struct notify_t notify;      /* Indication/Confirm entry points */
+	struct qos_info qos;         /* QoS for this connection */
+
+	struct lap_cb *lap; /* Pointer to LAP connection structure */
+};
+
+/*
+ *  Information about each registred IrLAP layer
+ */
+struct lap_cb {
+	QUEUE queue;      /* Must be first */
+
+	int magic;
+	int reason;    /* LAP disconnect reason */
+
+	IRLMP_STATE lap_state;
+
+	struct irlap_cb *irlap; /* Instance of IrLAP layer */
+
+	hashbin_t *lsaps;         /* LSAP associated with this link */
+
+	__u8  caddr;            /* Connection address */
+
+ 	__u32 saddr;  /* Source device address */
+ 	__u32 daddr;  /* Destination device address */
+	
+	hashbin_t *cachelog;    /* Discovered devices for this link */
+
+	struct qos_info *qos;  /* LAP QoS for this session */
+};
+
+/*
+ *  Used for caching the last slsap->dlsap->handle mapping
+ */
+typedef struct {
+	int valid;
+
+	__u8 slsap_sel;
+	__u8 dlsap_sel;
+	struct lsap_cb *lsap;
+} CACHE_ENTRY;
+
+/*
+ *  Main structure for IrLMP
+ */
+struct irlmp_cb {
+	int magic;
+
+	__u8 conflict_flag;
+	
+	/* int discovery; */
+
+	DISCOVERY  discovery_rsp; /* Discovery response to use by IrLAP */
+	DISCOVERY  discovery_cmd; /* Discovery command to use by IrLAP */
+
+	int free_lsap_sel;
+
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+	CACHE_ENTRY cache;  /* Caching last slsap->dlsap->handle mapping */
+#endif
+	struct timer_list discovery_timer;
+
+ 	hashbin_t *links;         /* IrLAP connection table */
+	hashbin_t *unconnected_lsaps;
+ 	hashbin_t *registry;
+
+	__u8 hint[2]; /* Hint bits */
+};
+
+/* Prototype declarations */
+int  irlmp_init(void);
+void irlmp_cleanup(void);
+
+struct lsap_cb *irlmp_open_lsap( __u8 slsap, struct notify_t *notify);
+void irlmp_close_lsap( struct lsap_cb *self);
+
+void irlmp_register_layer( int service, int type, int do_discovery, 
+			      DISCOVERY_CALLBACK);
+void irlmp_unregister_layer( int service, int type);
+
+void irlmp_register_irlap( struct irlap_cb *self, __u32 saddr, 
+			   struct notify_t *);
+void irlmp_unregister_irlap( __u32 saddr);
+
+void irlmp_connect_request( struct lsap_cb *, __u8 dlsap_sel, __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 *);
+void irlmp_connect_confirm( struct lsap_cb *, struct sk_buff *);
+
+
+void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, 
+				  struct sk_buff *userdata);
+void irlmp_disconnect_request( struct lsap_cb *, struct sk_buff *userdata);
+
+void irlmp_discovery_confirm( struct lap_cb *, hashbin_t *discovery_log);
+void irlmp_discovery_indication( struct lap_cb *, DISCOVERY *discovery);
+void irlmp_discovery_request( int nslots);
+DISCOVERY *irlmp_get_discovery_response(void);
+
+void irlmp_data_request( struct lsap_cb *, struct sk_buff *);
+void irlmp_udata_request( struct lsap_cb *, struct sk_buff *);
+void irlmp_data_indication( struct lsap_cb *, struct sk_buff *);
+void irlmp_udata_indication( struct lsap_cb *, struct sk_buff *);
+
+void irlmp_status_request(void);
+void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock);
+
+int  irlmp_slsap_inuse( __u8 slsap);
+__u8 irlmp_find_free_slsap(void);
+
+LM_REASON irlmp_convert_lap_reason( LAP_REASON);
+
+extern struct irlmp_cb *irlmp;
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlmp_event.h linux/include/net/irda/irlmp_event.h
--- v2.1.131/linux/include/net/irda/irlmp_event.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlmp_event.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,113 @@
+/*********************************************************************
+ *                
+ * Filename:      irlmp_event.h
+ * Version:       0.1
+ * Description:   IrDA-LMP event handling
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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 IRLMP_EVENT_H
+#define IRLMP_EVENT_H
+
+struct irlmp_cb;
+struct lsap_cb;
+struct lap_cb;
+
+/* LAP states */
+typedef enum {
+	/* IrLAP connection control states */
+	LAP_STANDBY,             /* No LAP connection */
+	LAP_U_CONNECT,           /* Starting LAP connection */
+	LAP_ACTIVE,              /* LAP connection is active */
+} IRLMP_STATE;
+
+/* LSAP connection control states */
+typedef enum {
+	LSAP_DISCONNECTED,        /* No LSAP connection */
+	LSAP_CONNECT,             /* Connect indication from peer */
+	LSAP_CONNECT_PEND,        /* Connect request from service user */
+	LSAP_DATA_TRANSFER_READY, /* LSAP connection established */          
+	LSAP_SETUP,               /* Trying to set up LSAP connection */
+	LSAP_SETUP_PEND,          /* Request to start LAP connection */
+} LSAP_STATE;
+
+typedef enum {
+	/* LSAP events */
+ 	LM_CONNECT_REQUEST,
+ 	LM_CONNECT_CONFIRM,
+	LM_CONNECT_RESPONSE,
+ 	LM_CONNECT_INDICATION, 	
+	
+	LM_DISCONNECT_INDICATION,
+	LM_DISCONNECT_REQUEST,
+
+ 	LM_DATA_REQUEST,
+	LM_UDATA_REQUEST,
+ 	LM_DATA_INDICATION,
+	LM_UDATA_INDICATION,
+
+	LM_WATCHDOG_TIMEOUT,
+
+	/* IrLAP events */
+	LM_LAP_CONNECT_REQUEST,
+ 	LM_LAP_CONNECT_INDICATION, 
+ 	LM_LAP_CONNECT_CONFIRM,
+ 	LM_LAP_DISCONNECT_INDICATION, 
+	LM_LAP_DISCONNECT_REQUEST,
+	LM_LAP_DISCOVERY_REQUEST,
+ 	LM_LAP_DISCOVERY_CONFIRM,
+
+} IRLMP_EVENT;
+
+/*
+ *  Information which is used by the current thread, when executing in the
+ *  state machine.
+ */
+struct irlmp_event {
+	IRLMP_EVENT *event;
+	struct sk_buff *skb;
+
+	__u8 hint;
+	__u32 daddr;
+	__u32 saddr;
+
+	__u8 slsap;
+	__u8 dlsap;
+
+	int reason;
+
+	DISCOVERY *discovery;
+};
+
+extern char *irlmp_state[];
+extern char *irlsap_state[];
+
+void irlmp_watchdog_timer_expired( unsigned long data);
+void irlmp_discovery_timer_expired( unsigned long data);
+
+void irlmp_next_station_state( IRLMP_STATE state);
+void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state);
+void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state);
+
+void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, 
+			 struct sk_buff *skb);
+void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, 
+			  struct sk_buff *skb);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irlmp_frame.h linux/include/net/irda/irlmp_frame.h
--- v2.1.131/linux/include/net/irda/irlmp_frame.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlmp_frame.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,57 @@
+/*********************************************************************
+ *                
+ * Filename:      irlmp_frame.h
+ * Version:       0.1
+ * Description:   
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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 IRMLP_FRAME_H
+#define IRMLP_FRAME_H
+
+#include <linux/skbuff.h>
+
+/* Frame opcodes */
+#define CONNECT_CMD    0x01
+#define CONNECT_CNF    0x81
+#define DISCONNECT     0x02
+#define ACCESSMODE_CMD 0x03
+#define ACCESSMODE_CNF 0x83
+
+#define CONTROL_BIT 0x80
+
+inline void irlmp_send_data_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, 
+				 int expedited, struct sk_buff *skb);
+void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap, 
+			 __u8 opcode, struct sk_buff *skb);
+void irlmp_link_data_indication( struct lap_cb *, int reliable, 
+				 struct sk_buff *);
+void irlmp_link_connect_indication( struct lap_cb *, 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);
+void irlmp_link_disconnect_indication( struct lap_cb *self, 
+				       struct irlap_cb *irlap, 
+				       LAP_REASON reason, 
+				       struct sk_buff *); 
+void irlmp_link_discovery_confirm( struct lap_cb *self, hashbin_t *log);
+/* void irlmp_link_disconnect_request( void); */
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h
--- v2.1.131/linux/include/net/irda/irmod.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irmod.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,263 @@
+/*********************************************************************
+ *                
+ * Filename:      irmod.h
+ * Version:       0.3
+ * Description:   IrDA module and utilities functions
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Dec 15 13:58:52 1997
+ * Modified at:   Mon Dec  7 01:40:35 1998
+ * 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 charg.
+ *     
+ ********************************************************************/
+
+#ifndef IRMOD_H
+#define IRMOD_H
+
+#include <linux/skbuff.h>
+#include <linux/miscdevice.h>
+
+#include <net/irda/irqueue.h>
+#include <net/irda/qos.h>
+
+#define IRMGR_IOC_MAGIC 'm'
+#define IRMGR_IOCTNPC     _IO(IRMGR_IOC_MAGIC, 1)
+#define IRMGR_IOC_MAXNR   1 
+
+/*
+ *  Events that we pass to the user space manager
+ */
+typedef enum {
+	EVENT_DEVICE_DISCOVERED = 0,
+	EVENT_REQUEST_MODULE,
+	EVENT_IRLAN_START,
+	EVENT_IRLAN_STOP,
+	EVENT_IRLPT_START,
+	EVENT_IRLPT_STOP,
+	EVENT_IROBEX_START,
+	EVENT_IROBEX_STOP,
+	EVENT_IRDA_STOP,
+	EVENT_NEED_PROCESS_CONTEXT,
+} IRMGR_EVENT;
+
+/*
+ *  Event information passed to the IrManager daemon process
+ */
+struct irmanager_event {
+	IRMGR_EVENT event;
+	char devname[10];
+	char info[32];
+	int service;
+	__u32 saddr;
+	__u32 daddr;
+};
+
+typedef void (*TODO_CALLBACK)( void *self, __u32 param);
+
+/*
+ *  Same as irmanager_event but this one can be queued and inclueds some
+ *  addtional information
+ */
+struct irda_event {
+	QUEUE q; /* Must be first */
+	
+	struct irmanager_event event;
+};
+
+/*
+ *  Funtions with needs to be called with a process context
+ */
+struct irda_todo {
+	QUEUE q; /* Must be first */
+
+	void *self;
+	TODO_CALLBACK callback;
+	__u32 param;
+};
+
+/*
+ *  Main structure for the IrDA device (not much here :-)
+ */
+struct irda {
+	struct miscdevice dev;	
+	struct wait_queue *wait_queue;
+
+	QUEUE *event_queue; /* Events queued for the irmanager */
+	QUEUE *todo_queue;  /* Todo list */
+};
+
+typedef struct {
+        char irda_call[7];  /* 6 call + SSID (shifted ascii!) */
+} irda_address;
+
+struct sockaddr_irda {
+	short sirda_family;
+	irda_address sirda_call;
+        int sirda_ndigis;
+};
+
+/*
+ *  This type is used by the protocols that transmit 16 bits words in 
+ *  little endian format. A little endian machine stores MSB of word in
+ *  byte[1] and LSB in byte[0]. A big endian machine stores MSB in byte[0] 
+ *  and LSB in byte[1].
+ */
+typedef union {
+	__u16 word;
+	__u8  byte[2];
+} __u16_host_order;
+
+/*
+ *  Information monitored by some layers
+ */
+struct irda_statistics
+{
+        int     rx_packets;             /* total packets received       */
+        int     tx_packets;             /* total packets transmitted    */
+        int     rx_errors;              /* bad packets received         */
+        int     tx_errors;              /* packet transmit problems     */
+        int     rx_dropped;             /* no space in linux buffers    */
+        int     tx_dropped;             /* no space available in linux  */
+	int     rx_compressed;
+	int     tx_compressed;
+	int     rx_bytes;               /* total bytes received         */
+	int     tx_bytes;               /* total bytes transmitted      */
+
+        int     multicast;              /* multicast packets received   */
+        int     collisions;
+	
+        /* detailed rx_errors: */
+        int     rx_length_errors;
+        int     rx_over_errors;         /* receiver ring buff overflow  */
+        int     rx_crc_errors;          /* recved pkt with crc error    */
+        int     rx_frame_errors;        /* recv'd frame alignment error */
+        int     rx_fifo_errors;         /* recv'r fifo overrun          */
+        int     rx_missed_errors;       /* receiver missed packet       */
+
+        /* detailed tx_errors */
+        int     tx_aborted_errors;
+        int     tx_carrier_errors;
+        int     tx_fifo_errors;
+        int     tx_heartbeat_errors;
+        int     tx_window_errors;
+};
+
+typedef enum {
+	NO_CHANGE,
+	LOCKED,
+	UNLOCKED,
+} LOCK_STATUS;
+
+/* Misc status information */
+typedef enum {
+	STATUS_OK,
+	STATUS_ABORTED,
+	STATUS_NO_ACTIVITY,
+	STATUS_NOISY,
+	STATUS_REMOTE,
+} LINK_STATUS;
+
+typedef enum { /* FIXME check the two first reason codes */
+	LAP_DISC_INDICATION=1, /* Received a disconnect request from peer */
+	LAP_NO_RESPONSE,       /* To many retransmits without response */
+	LAP_RESET_INDICATION,  /* To many retransmits, or invalid nr/ns */
+	LAP_FOUND_NONE,        /* No devices were discovered */
+	LAP_MEDIA_BUSY,
+	LAP_PRIMARY_CONFLICT,
+} LAP_REASON;
+
+/*  
+ *  IrLMP disconnect reasons. The order is very important, since they 
+ *  correspond to disconnect reasons sent in IrLMP disconnect frames, so
+ *  please do not touch :-)
+ */
+typedef enum {
+	LM_USER_REQUEST = 1,  /* User request */
+	LM_LAP_DISCONNECT,    /* Unexpected IrLAP disconnect */
+	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 */
+
+/*
+ *  IrLMP character code values
+ */
+#define CS_ASCII       0x00
+#define	CS_ISO_8859_1  0x01
+#define	CS_ISO_8859_2  0x02
+#define	CS_ISO_8859_3  0x03
+#define	CS_ISO_8859_4  0x04
+#define	CS_ISO_8859_5  0x05
+#define	CS_ISO_8859_6  0x06
+#define	CS_ISO_8859_7  0x07
+#define	CS_ISO_8859_8  0x08
+#define	CS_ISO_8859_9  0x09
+#define CS_UNICODE     0xff
+	
+/*
+ * The DISCOVERY structure is used for both discovery requests and responses
+ */
+#define DISCOVERY struct discovery_t
+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 */
+
+	int         gen_addr_bit; /* Need to generate a new device address? */
+};
+
+typedef enum { FLOW_STOP, FLOW_START } LOCAL_FLOW;
+
+/*
+ *  Notify structure used between transport and link management layers
+ */
+struct notify_t {
+	void (*data_indication)( void *instance, void *sap, 
+				 struct sk_buff *skb);
+	void (*udata_indication)( void *instance, void *sap, 
+				  struct sk_buff *skb);
+	void (*connect_confirm)( void *instance, void *sap, 
+				 struct qos_info *qos, int max_sdu_size,
+				 struct sk_buff *skb);
+	void (*connect_indication)( void *instance, void *sap, 
+				    struct qos_info *qos, int max_sdu_size,
+				    struct sk_buff *skb);
+	void (*disconnect_indication)( void *instance, void *sap, 
+				       LM_REASON reason, struct sk_buff *);
+	void (*flow_indication)( void *instance, void *sap, LOCAL_FLOW flow);
+	void *instance; /* Layer instance pointer */
+	char name[16];  /* Name of layer */
+};
+
+#define NOTIFY_MAX_NAME 16
+
+int irmod_init_module(void);
+void irmod_cleanup_module(void);
+
+inline int irda_lock( int *lock);
+inline int irda_unlock( int *lock);
+
+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);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irobex.h linux/include/net/irda/irobex.h
--- v2.1.131/linux/include/net/irda/irobex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irobex.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,134 @@
+/*********************************************************************
+ *                
+ * Filename:      irobex.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Jul  4 22:43:57 1998
+ * Modified at:   Mon Oct 19 12:32:33 1998
+ * 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 IROBEX_H
+#define IROBEX_H
+
+#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>
+#include <net/irda/qos.h>
+#include <net/irda/irmod.h>
+
+#define LOW_THRESHOLD      4
+#define HIGH_THRESHOLD     8
+#define IROBEX_MAX_QUEUE  12
+
+/* Small structure to be used by the IOCTL call */
+struct irobex_ioc_t {
+     __u32 daddr;
+};
+
+#define IROBEX_IOC_MAGIC 'k'
+
+#define IROBEX_IOCSCONNECT    _IOW(IROBEX_IOC_MAGIC, 1, 4)
+#define IROBEX_IOCSDISCONNECT _IOW(IROBEX_IOC_MAGIC, 2, 4)
+#define IROBEX_IOC_MAXNR 2
+
+
+#define IROBEX_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+
+struct irobex_cb {
+	QUEUE queue;        /* Must be first! */
+
+        int magic;          /* magic used to detect corruption of the struct */
+
+	__u32 saddr;        /* my local address */
+	__u32 daddr;        /* peer address */
+	unsigned long time_discovered;
+
+        char devname[9];    /* name of the registered device */
+	struct tsap_cb *tsap;
+	int connected;
+	int eof;
+
+	__u8 dtsap_sel;         /* remote TSAP address */
+	__u8 stsap_sel;         /* local TSAP address */
+
+	int irlap_data_size;
+
+	struct miscdevice dev;
+
+	int count;                /* open count */
+
+	struct sk_buff_head rx_queue; /* Receive queue */
+
+	struct wait_queue *read_wait;
+	struct wait_queue *write_wait;
+
+	/* These wait queues are used for setting up a connections */
+	struct wait_queue *connect_wait;
+	struct wait_queue *discover_wait;
+	struct wait_queue *ias_wait;
+
+	struct fasync_struct *async;
+
+	struct timer_list watchdog_timer;
+
+	LOCAL_FLOW tx_flow;
+	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);
+
+void irobex_watchdog_timer_expired( unsigned long data);
+
+inline void irobex_start_watchdog_timer( struct irobex_cb *self, 
+						int timeout) 
+{
+	irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self,
+			  irobex_watchdog_timer_expired);
+}
+
+
+extern struct irobex_cb *irobex;
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.1.131/linux/include/net/irda/irport.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irport.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,61 @@
+/*********************************************************************
+ *                
+ * Filename:      irport.h
+ * Version:       0.1
+ * Description:   Serial driver for IrDA
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug  3 13:49:59 1997
+ * Modified at:   Wed Nov  4 15:10:41 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997, 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 IRPORT_H
+#define IRPORT_H
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+
+#include <irda_device.h>
+
+#define SPEED_DEFAULT 9600
+#define SPEED_MAX     115200
+
+/*
+ * These are the supported serial types.
+ */
+#define PORT_UNKNOWN    0
+#define PORT_8250       1
+#define PORT_16450      2
+#define PORT_16550      3
+#define PORT_16550A     4
+#define PORT_CIRRUS     5
+#define PORT_16650      6
+#define PORT_MAX        6  
+
+#define FRAME_MAX_SIZE 2048
+
+void irport_close( int iobase);
+int  irport_open( int iobase);
+int  irport_detect(struct irda_device *idev);
+
+void irport_change_speed( int iobase, int speed);
+void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+int  irport_hard_xmit( struct sk_buff *skb, struct device *dev);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irqueue.h linux/include/net/irda/irqueue.h
--- v2.1.131/linux/include/net/irda/irqueue.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irqueue.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,106 @@
+/*********************************************************************
+ *                
+ * Filename:      irqueue.h
+ * Version:       0.3
+ * Description:   General queue implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Tue Jun  9 13:26:50 1998
+ * Modified at:   Sun Oct 25 00:26:31 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
+ *     Copyright (c) 1998, Dag Brattli
+ *     All Rights Reserved.
+ *      
+ *     This code is taken from the Vortex Operating System written by Aage
+ *     Kvalnes and has been ported to Linux and Linux/IR by Dag Brattli
+ *
+ *     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/types.h>
+#include <asm/spinlock.h>
+
+#include <net/irda/irda.h>
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#define NAME_SIZE      32
+
+/*
+ * Hash types
+ */
+#define HB_NOLOCK      0
+#define HB_GLOBAL      1
+#define HB_LOCAL       2
+#define HB_SORTED      4
+
+/*
+ * Hash defines
+ */
+#define HASHBIN_SIZE   8
+#define HASHBIN_MASK   0x7
+
+typedef void (*FREE_FUNC)( void *arg);
+
+/*
+ * Hashbin
+ */
+#define GET_HASHBIN(x) ( x & HASHBIN_MASK )
+
+#define QUEUE struct queue_t
+struct queue_t {
+	QUEUE* q_next;
+	QUEUE* q_prev;
+
+	char   q_name[ NAME_SIZE];
+	__u32  q_hash;
+};
+
+typedef struct hashbin_t {
+	int    magic;
+	int    hb_type;
+	int    hb_size;
+	spinlock_t hb_mutex[ HASHBIN_SIZE ] ALIGN;
+	QUEUE*     hb_queue[ HASHBIN_SIZE ] ALIGN;
+
+	QUEUE* hb_current;
+} hashbin_t;
+
+hashbin_t *hashbin_new( int type);
+int      hashbin_delete( hashbin_t* hashbin, FREE_FUNC func);
+int      hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func);
+void     hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
+			 char* name);
+void*    hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name);
+void*    hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name);
+void*    hashbin_remove_first( hashbin_t *hashbin);
+QUEUE   *hashbin_get_first( hashbin_t *hashbin);
+QUEUE   *hashbin_get_next( hashbin_t *hashbin);
+
+void enqueue_last(QUEUE **queue, QUEUE* element);
+void enqueue_first(QUEUE **queue, QUEUE* element);
+QUEUE *dequeue_first(QUEUE **queue);
+
+/*
+ * Function hashbin_get_size (hashbin)
+ *
+ *    Returns the number of elements in the hashbin
+ *
+ */
+extern __inline__ int  hashbin_get_size( hashbin_t* hashbin) 
+{
+	return hashbin->hb_size;
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irttp.h linux/include/net/irda/irttp.h
--- v2.1.131/linux/include/net/irda/irttp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irttp.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,136 @@
+/*********************************************************************
+ *                
+ * Filename:      irttp.h
+ * Version:       0.3
+ * 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 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 IRTTP_H
+#define IRTTP_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include <net/irda/irmod.h>
+#include <net/irda/irlmp.h>
+#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 DEFAULT_INITIAL_CREDIT 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 SAR_DISABLE 0
+
+/*
+ *  This structure contains all data assosiated with one instance of a TTP 
+ *  connection.
+ */
+struct tsap_cb {
+	QUEUE queue;         /* For linking it into the hashbin */
+	int  magic;          /* Just in case */
+
+	int max_seg_size;    /* Max data that fit into an IrLAP frame */
+
+	__u8 stsap_sel;      /* Source TSAP */
+	__u8 dtsap_sel;      /* Destination TSAP */
+
+	struct lsap_cb *lsap; /* Corresponding LSAP to this TSAP */
+
+	__u8 connected;       /* TSAP connected */
+	 
+	__u8 initial_credit;  /* Initial credit to give peer */
+
+        int avail_credit;    /* Available credit to return to peer */
+	int remote_credit;   /* Credit held by peer TTP entity */
+	int send_credit;     /* Credit held by local TTP entity */
+	
+	struct sk_buff_head tx_queue; /* Frames to be transmitted */
+	struct sk_buff_head rx_queue; /* Received frames */
+	struct sk_buff_head rx_fragments;
+	int tx_queue_lock;
+	int rx_queue_lock;
+
+	struct notify_t notify;       /* Callbacks to client layer */
+
+	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_max_sdu_size; /* Max receive user data size */
+
+	int tx_sdu_busy;     /* TxSdu.busy */
+	int tx_max_sdu_size; /* Max transmit user data size */
+
+        int no_defrag;       /* Don't reassemble received fragments */
+
+	int disconnect_pend;   /* Disconnect, but still data to send */
+	struct sk_buff *disconnect_skb;
+};
+
+struct irttp_cb {
+	int magic;
+	
+	hashbin_t *tsaps;
+};
+
+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 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)
+{
+	self->no_defrag = TRUE;
+}
+
+extern struct irttp_cb *irttp;
+
+#endif /* IRTTP_H */
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irtty.h linux/include/net/irda/irtty.h
--- v2.1.131/linux/include/net/irda/irtty.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irtty.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,68 @@
+/*********************************************************************
+ *                
+ * Filename:      irtty.h
+ * Version:       0.1
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ *  
+ *     Copyright (c) 1997 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 IRTTY_H
+#define IRTTY_H
+
+#include <linux/if.h>
+#include <linux/skbuff.h>
+#include <linux/termios.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irqueue.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/dongle.h>
+
+#define IRTTY_IOC_MAGIC 'e'
+#define IRTTY_IOCTDONGLE  _IO(IRTTY_IOC_MAGIC, 1)
+#define IRTTY_IOC_MAXNR   1
+
+#ifndef N_IRDA
+#define N_IRDA         11   /* This one should go in </asm/termio.h> */
+#endif
+
+struct dongle_q {
+	QUEUE q;
+
+	struct dongle *dongle;
+};
+
+struct irtty_cb {
+	QUEUE q; /* Must be first */
+
+/* 	char name[16]; */
+
+	int	magic;
+	
+	struct  tty_struct  *tty;  /* Ptr to TTY structure */
+	struct  irda_device idev;
+
+	struct dongle_q *dongle_q; /* Has this tty got a dongle attached? */
+};
+ 
+int irtty_register_dongle( struct dongle *dongle);
+void irtty_unregister_dongle( struct dongle *dongle);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irvtd.h linux/include/net/irda/irvtd.h
--- v2.1.131/linux/include/net/irda/irvtd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irvtd.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,104 @@
+/*********************************************************************
+ *                
+ * Filename:      irvtd.h
+ * Version:       0.1
+ * Sources:       irlpt.h
+ * 
+ *     Copyright (c) 1998, Takahide Higuchi <thiguchi@pluto.dti.ne.jp>,
+ *     All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRCOMM_H
+#define IRCOMM_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <linux/tqueue.h>
+
+#include <net/irda/irmod.h>
+#include <net/irda/qos.h>
+#include <net/irda/ircomm_common.h>
+
+
+#define IRVTD_MAGIC 0xff545943  /* random */
+#define COMM_MAX_TTY 1
+#define IRVTD_RX_QUEUE_HIGH 10
+#define IRVTD_RX_QUEUE_LOW  2
+
+
+/*
+ * Serial input interrupt line counters -- external structure
+ * Four lines can interrupt: CTS, DSR, RI, DCD
+ *
+ * this structure must be compatible with serial_icounter_struct defined in
+ * <linux/serial.h>.
+ */
+struct icounter_struct {
+        int cts, dsr, rng, dcd;
+        int reserved[16];
+};
+
+struct irvtd_cb {
+
+        int magic;          /* magic used to detect corruption of the struct */
+
+	/* if daddr is NULL, remote device have not been discovered yet */
+
+	int rx_disable;
+	struct sk_buff *txbuff;     /* buffer queue */
+	struct sk_buff_head rxbuff;     /* buffer queue */
+	struct ircomm_cb *comm;     /* ircomm instance */
+
+	/* 
+	 * These members are used for compatibility with usual serial device.
+	 * See linux/serial.h
+	 */
+
+	int baud_base;
+	int flags;
+	struct tty_struct *tty;
+
+	int line;
+	int count;                /* open count */
+	int blocked_open;
+	struct wait_queue       *open_wait;
+	struct wait_queue       *close_wait;
+	struct wait_queue       *delta_msr_wait;
+	struct wait_queue       *tx_wait;
+
+	struct tq_struct        rx_tqueue;
+
+	long pgrp;
+	long session;  
+	struct termios normal_termios;
+	struct termios callout_termios;
+	unsigned short  closing_wait;     /* time to wait before closing */
+	unsigned short  close_delay;
+	
+	int mcr;
+	int msr;
+	int cts_stoptx;
+	int ttp_stoptx;
+	int ttp_stoprx;
+	struct icounter_struct icount;
+	int read_status_mask;
+	int ignore_status_mask;
+};
+
+
+/* Debug function */
+
+/* #define CHECK_SKB(skb) check_skb((skb),  __LINE__,__FILE__) */
+
+
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/irvtd_driver.h linux/include/net/irda/irvtd_driver.h
--- v2.1.131/linux/include/net/irda/irvtd_driver.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irvtd_driver.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,122 @@
+/*********************************************************************
+ *                
+ * Filename:      irvtd_driver.h
+ * Version:       0.1
+ * 
+ *     Copyright (c) 1998, Takahide Higuchi <thiguchi@pluto.dti.ne.jp>, 
+ *     All Rights Reserved.
+ *     
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software. 
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/tty.h>
+
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+
+#define VSP_TYPE_NORMAL   1
+#define VSP_TYPE_CALLOUT  2
+#define IRCOMM_MAJOR  60;  /* Zero means automatic allocation
+                              60,61,62,and 63 is reserved for experiment */
+#define IRVTD_MINOR 64
+#define IRVTD_CALLOUT_MINOR 32
+
+#define IRVTD_TYPE_NORMAL 11
+#define IRVTD_TYPE_CALLOUT 12
+
+
+#define IRCOMM_HEADER 1       
+#define IRCOMM_RESERVE LAP_HEADER+LMP_HEADER+TTP_HEADER+IRCOMM_HEADER
+
+
+
+
+
+/*
+ * Definitions for ircomm_cb_struct flags field
+ *  this section is "stolen" from linux-kernel (drivers/char/serial.c)
+ */
+#define IRVTD_ASYNC_HUP_NOTIFY 0x0001 /* Notify getty on hangups and closes 
+				   on the callout port */
+/* #define IRVTD_ASYNC_FOURPORT  0x0002 */
+/* Set OU1, OUT2 per AST Fourport settings */
+
+#define IRVTD_ASYNC_SAK	0x0004	/* Secure Attention Key (Orange book) */
+
+#define IRVTD_ASYNC_SPLIT_TERMIOS 0x0008 /* Separate termios for dialin/callout */
+
+#define IRVTD_ASYNC_SPD_MASK	0x0030
+#define IRVTD_ASYNC_SPD_HI	0x0010	/* Use 56000 instead of 38400 bps */
+
+#define IRVTD_ASYNC_SPD_VHI	0x0020  /* Use 115200 instead of 38400 bps */
+#define IRVTD_ASYNC_SPD_CUST	0x0030  /* Use user-specified divisor */
+
+#define IRVTD_ASYNC_SKIP_TEST	0x0040  /* Skip UART test during autoconfiguration */
+#define IRVTD_ASYNC_AUTO_IRQ    0x0080  /* Do automatic IRQ during autoconfiguration */
+#define IRVTD_ASYNC_SESSION_LOCKOUT 0x0100 /* Lock out cua opens based on session */
+#define IRVTD_ASYNC_PGRP_LOCKOUT    0x0200  /* Lock out cua opens based on pgrp */
+#define IRVTD_ASYNC_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
+
+#define IRVTD_ASYNC_FLAGS	0x0FFF	/* Possible legal async flags */
+#define IRVTD_ASYNC_USR_MASK 0x0430	/* Legal flags that non-privileged
+				 * users can set or reset */
+
+/* Internal flags used only by kernel/chr_drv/serial.c */
+#define IRVTD_ASYNC_INITIALIZED	0x80000000 /* Serial port was initialized */
+#define IRVTD_ASYNC_CALLOUT_ACTIVE	0x40000000 /* Call out device is active */
+#define IRVTD_ASYNC_NORMAL_ACTIVE	0x20000000 /* Normal device is active */
+#define IRVTD_ASYNC_BOOT_AUTOCONF	0x10000000 /* Autoconfigure port on bootup */
+#define IRVTD_ASYNC_CLOSING		0x08000000 /* Serial port is closing */
+#define IRVTD_ASYNC_CTS_FLOW		0x04000000 /* Do CTS flow control */
+#define IRVTD_ASYNC_CHECK_CD		0x02000000 /* i.e., CLOCAL */
+#define IRVTD_ASYNC_SHARE_IRQ		0x01000000 /* for multifunction cards */
+
+
+#define IRVTD_ASYNC_CLOSING_WAIT_INF  0
+#define IRVTD_ASYNC_CLOSING_WAIT_NONE 65535
+
+/**************************************/
+
+#define DELTA_DTR 0x01
+#define DELTA_RTS 0x02
+#define MCR_DTR 0x04
+#define MCR_RTS 0x08
+
+#define DELTA_CTS 0x01
+#define DELTA_DSR 0x02
+#define DELTA_RI  0x04 
+#define DELTA_DCD 0x08
+#define MSR_CTS   0x10
+#define MSR_DSR   0x20
+#define MSR_RI    0x40 
+#define MSR_DCD   0x80
+
+#define LSR_OE     0x02    /* Overrun error indicator */
+#define LSR_PE     0x04    /* Parity error indicator */
+#define LSR_FE     0x08    /* Frame error indicator */
+#define LSR_BI     0x01    /* Break interrupt indicator */
+
+
+
+/**************************************/
+
+
+
+
+int irvtd_register_ttydriver(void);
+void irvtd_unregister_ttydriver(void);
+
+void irvtd_flush_chars(struct tty_struct *tty);
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/pc87108.h linux/include/net/irda/pc87108.h
--- v2.1.131/linux/include/net/irda/pc87108.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/pc87108.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,194 @@
+/*********************************************************************
+ *                
+ * Filename:      pc87108.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Nov 13 14:37:40 1998
+ * Modified at:   Thu Dec 10 19:58:20 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>
+ *     Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ *     Copyright (c) 1998 Actisys Corp., www.actisys.com
+ *     All Rights Reserved
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     the License, or (at your option) any later version.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef PC87108_H
+#define PC87108_H
+
+#include <asm/io.h>
+
+/* Flags for configuration register CRF0 */
+#define APEDCRC		0x02
+#define ENBNKSEL	0x01
+
+/* Set 0 */
+#define TXD             0x00 /* Transmit data port */
+#define RXD             0x00 /* Receive data port */
+
+/* Register 1 */
+#define IER		0x01 /* Interrupt Enable Register*/
+#define IER_RXHDL_IE    0x01 /* Receiver high data level interrupt */
+#define IER_TXLDL_IE    0x02 /* Transeiver low data level interrupt */
+#define IER_LS_IE	0x04//* Link Status Interrupt */
+#define IER_ETXURI      0x04 /* Tx underrun */
+#define IER_DMA_IE	0x10 /* DMA finished interrupt */
+#define IER_TXEMP_IE    0x20
+#define IER_SFIF_IE     0x40 /* Frame status FIFO intr */
+#define IER_TMR_IE      0x80 /* Timer event */
+
+#define FCR		0x02 /* (write only) */
+#define FCR_FIFO_EN     0x01 /* Enable FIFO's */
+#define FCR_RXSR        0x02 /* Rx FIFO soft reset */
+#define FCR_TXSR        0x04 /* Tx FIFO soft reset */
+#define FCR_RXTH	0x80 /* Rx FIFO threshold (set to 16) */
+#define FCR_TXTH	0x20 /* Tx FIFO threshold (set to 17) */
+
+#define EIR		0x02 /* (read only) */
+#define EIR_RXHDL_EV	0x01
+#define EIR_TXLDL_EV    0x02
+#define EIR_LS_EV	0x04
+#define EIR_DMA_EV	0x10
+#define EIR_TXEMP_EV	0x20
+#define EIR_SFIF_EV     0x40
+#define EIR_TMR_EV      0x80
+
+#define LCR             0x03 /* Link control register */
+#define LCR_WLS_8       0x03 /* 8 bits */
+
+#define BSR 	        0x03 /* Bank select register */
+#define BSR_BKSE        0x80
+#define BANK0 	        LCR_WLS_8 /* Must make sure that we set 8N1 */
+#define BANK1	        0x80
+#define BANK2	        0xe0
+#define BANK3	        0xe4
+#define BANK4	        0xe8
+#define BANK5	        0xec
+#define BANK6	        0xf0
+#define BANK7     	0xf4
+
+#define MCR		0x04 /* Mode Control Register */
+#define MCR_MODE_MASK	~(0xd0)
+#define MCR_UART        0x00
+#define MCR_RESERVED  	0x20	
+#define MCR_SHARP_IR    0x40
+#define MCR_SIR         0x60
+#define MCR_MIR  	0x80
+#define MCR_FIR		0xa0
+#define MCR_CEIR        0xb0
+#define MCR_DMA_EN	0x04
+#define MCR_EN_IRQ	0x08
+#define MCR_TX_DFR	0x08
+
+#define LSR             0x05 /* Link status register */
+#define LSR_RXDA        0x01 /* Receiver data available */
+#define LSR_TXRDY       0x20 /* Transmitter ready */
+#define LSR_TXEMP       0x40 /* Transmitter empty */
+
+#define ASCR            0x07 /* Auxillary Status and Control Register */
+#define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
+#define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
+#define ASCR_S_EOT      0x04 /* Set end of transmission */
+#define ASCT_RXBSY      0x20 /* Rx busy */
+#define ASCR_TXUR       0x40 /* Transeiver underrun */
+#define ASCR_CTE        0x80 /* Clear timer event */
+
+/* Bank 2 */
+#define BGDL            0x00 /* Baud Generator Divisor Port (Low Byte) */
+#define BGDH            0x01 /* Baud Generator Divisor Port (High Byte) */
+
+#define ECR1		0x02 /* Extended Control Register 1 */
+#define ECR1_EXT_SL	0x01 /* Extended Mode Select */
+#define ECR1_DMANF	0x02 /* DMA Fairness */
+#define ECR1_DMATH      0x04
+#define ECR1_DMASWP	0x08 /* DMA Swap */
+
+#define EXCR2		0x04
+#define EXCR2_TFSIZ	0x01 /* Rx FIFO size = 32 */
+#define EXCR2_RFSIZ	0x04 /* Tx FIFO size = 32 */
+
+#define TXFLV           0x06 /* Tx FIFO level */
+#define RXFLV           0x07 /* Rx FIFO level */
+
+/* Bank 3 */
+#define MID		0x00
+
+/* Bank 4 */
+#define TMRL            0x00 /* Timer low byte */
+#define TMRH            0x01 /* Timer high byte */
+#define IRCR1           0x02 /* Infrared control register 1 */
+#define IRCR1_TMR_EN    0x01 /* Timer enable */
+
+#define TFRLL		0x04
+#define TFRLH		0x05
+#define RFRLL		0x06
+#define RFRLH		0x07
+
+/* Bank 5 */
+#define IRCR2           0x04 /* Infrared control register 2 */
+#define IRCR2_MDRS      0x04 /* MIR data rate select */
+#define IRCR2_FEND_MD   0x20 /* */
+
+#define FRM_ST          0x05 /* Frame status FIFO */
+#define FRM_ST_VLD      0x80 /* Frame status FIFO data valid */
+#define FRM_ST_ERR_MSK  0x5f
+#define FRM_ST_LOST_FR  0x40 /* Frame lost */
+#define FRM_ST_MAX_LEN  0x10 /* Max frame len exceeded */
+#define FRM_ST_PHY_ERR  0x08 /* Physical layer error */
+#define FRM_ST_BAD_CRC  0x04 
+#define FRM_ST_OVR2     0x02 /* Receive overrun */
+#define FRM_ST_OVR1     0x01 /* Frame status FIFO overrun */
+
+#define RFLFL           0x06
+#define RFLFH           0x07
+
+/* Bank 6 */
+#define IR_CFG2		0x00
+#define IR_CFG2_DIS_CRC	0x02
+
+/* Bank 7 */
+#define IRM_CR		0x07 /* Infrared module control register */
+#define IRM_CR_IRX_MSL	0x40
+#define IRM_CR_AF_MNT   0x80 /* Automatic format */
+
+/* For storing entries in the status FIFO */
+struct st_fifo_entry {
+	int status;
+	int len;
+};
+
+struct st_fifo {
+	struct st_fifo_entry entries[10];
+	int head;
+	int tail;
+	int len;
+};
+
+/* Private data for each instance */
+struct pc87108 {
+	struct st_fifo st_fifo;
+
+	int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
+	int tx_len;          /* Number of frames in tx_buff */
+
+	struct irda_device idev;
+};
+
+static inline void switch_bank( int iobase, int bank)
+{
+		outb( bank, iobase+BSR);
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/qos.h linux/include/net/irda/qos.h
--- v2.1.131/linux/include/net/irda/qos.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/qos.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,104 @@
+/*********************************************************************
+ *                
+ * Filename:      qos.h
+ * Version:       0.1
+ * Description:   Quality of Service definitions
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Sep 19 23:21:09 1997
+ * Modified at:   Wed Dec  9 10:32:47 1998
+ * Modified 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 QOS_H
+#define QOS_H
+
+#include <linux/config.h>
+#include <linux/skbuff.h>
+
+#define PI_BAUD_RATE     0x01
+#define PI_MAX_TURN_TIME 0x82
+#define PI_DATA_SIZE     0x83
+#define PI_WINDOW_SIZE   0x84
+#define PI_ADD_BOFS      0x85
+#define PI_MIN_TURN_TIME 0x86
+#define PI_LINK_DISC     0x08
+#define PI_COMPRESSION   0x07 /* Just a random pick */
+
+
+#define IR_115200_MAX 0x3f
+
+/* Baud rates (first byte) */
+#define IR_2400    0x01
+#define IR_9600    0x02
+#define IR_19200   0x04
+#define IR_38400   0x08
+#define IR_57600   0x10
+#define IR_115200  0x20
+#define IR_576000  0x40
+#define IR_1152000 0x80
+
+/* Baud rates (second byte) */
+#define IR_4000000 0x01
+
+/* Quality of Service information */
+typedef struct {
+	int value;
+	__u16 bits; /* LSB is first byte, MSB is second byte */
+} qos_value_t;
+
+struct qos_info {
+	int  magic;
+
+	qos_value_t baud_rate;       /* IR_11520O | ... */
+	qos_value_t max_turn_time;
+	qos_value_t data_size;
+	qos_value_t window_size;
+	qos_value_t additional_bofs;
+	qos_value_t min_turn_time;
+	qos_value_t link_disc_time;
+	
+	qos_value_t power;
+#ifdef CONFIG_IRDA_COMPRESSION
+	/* An experimental non IrDA field */
+	qos_value_t compression;
+#endif
+};
+
+extern int baud_rates[];
+extern int data_size[];
+extern int min_turn_time[];
+extern int add_bofs[];
+extern int compression[];
+
+void irda_init_max_qos_capabilies( struct qos_info *qos);
+void irda_qos_compute_intersection( struct qos_info *, struct qos_info *);
+int  irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *fp);
+void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx,
+			 struct sk_buff *skb);
+
+int msb_index ( __u16 byte);
+int byte_value( __u8 byte, int *array);
+int value_index( int value, int *array);
+int index_value( int index, int *array);
+
+void irda_qos_bits_to_value( struct qos_info *qos);
+
+#endif
+
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/smc_ircc.h linux/include/net/irda/smc_ircc.h
--- v2.1.131/linux/include/net/irda/smc_ircc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/smc_ircc.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,123 @@
+#if 0
+static char *rcsid = "$Id: smc_ircc.h,v 1.5 1998/07/27 01:25:29 ratbert Exp $";
+#endif
+
+#ifndef SMC_IRCC_H
+#define SMC_IRCC_H
+
+#define FIR_XMIT	1
+#define FIR_RECEIVE	2
+#define SIR_XMIT	3
+#define SIR_RECEIVE	4
+
+#define MASTER			0x07
+#define MASTER_POWERDOWN	1<<7
+#define MASTER_RESET		1<<6
+#define MASTER_INT_EN		1<<5
+#define MASTER_ERROR_RESET	1<<4
+
+/* Register block 0 */
+
+#define IIR	0x01
+#define IER	0x02
+#define LSR	0x03
+#define LCR_A	0x04
+#define LCR_B	0x05
+#define BSR	0x06
+
+#define IIR_ACTIVE_FRAME	1<<7
+#define IIR_EOM 		1<<6
+#define IIR_RAW_MODE		1<<5
+#define IIR_FIFO		1<<4
+
+#define IER_ACTIVE_FRAME	1<<7
+#define IER_EOM 		1<<6
+#define IER_RAW_MODE		1<<5
+#define IER_FIFO		1<<4
+
+#define LSR_UNDER_RUN		1<<7
+#define LSR_OVER_RUN		1<<6
+#define LSR_FRAME_ERROR 	1<<5
+#define LSR_SIZE_ERROR		1<<4
+#define LSR_CRC_ERROR		1<<3
+#define LSR_FRAME_ABORT 	1<<2
+
+#define LCR_A_FIFO_RESET        1<<7
+#define LCR_A_FAST              1<<6
+#define LCR_A_GP_DATA           1<<5
+#define LCR_A_RAW_TX            1<<4
+#define LCR_A_RAW_RX            1<<3
+#define LCR_A_ABORT             1<<2
+#define LCR_A_DATA_DONE         1<<1
+
+#define LCR_B_SCE_MODE_DISABLED 	0x00<<6
+#define LCR_B_SCE_MODE_TRANSMIT 	0x01<<6
+#define LCR_B_SCE_MODE_RECEIVE		0x02<<6
+#define LCR_B_SCE_MODE_UNDEFINED	0x03<<6
+#define LCR_B_SIP_ENABLE		1<<5
+#define LCR_B_BRICK_WALL		1<<4
+
+#define BSR_NOT_EMPTY	1<<7
+#define BSR_FIFO_FULL	1<<6
+#define BSR_TIMEOUT	1<<5
+
+/* Register block 1 */
+
+#define SCE_CFG_A	0x00
+#define SCE_CFG_B	0x01
+#define FIFO_THRESHOLD	0x02
+
+#define CFG_A_AUX_IR		0x01<<7
+#define CFG_A_HALF_DUPLEX	0x01<<2
+#define CFG_A_TX_POLARITY	0x01<<1
+#define CFG_A_RX_POLARITY	0x01
+
+#define CFG_A_COM		0x00<<3
+#define CFG_A_IRDA_SIR_A	0x01<<3
+#define CFG_A_ASK_SIR		0x02<<3
+#define CFG_A_IRDA_SIR_B	0x03<<3
+#define CFG_A_IRDA_HDLC 	0x04<<3
+#define CFG_A_IRDA_4PPM 	0x05<<3
+#define CFG_A_CONSUMER		0x06<<3
+#define CFG_A_RAW_IR		0x07<<3
+#define CFG_A_OTHER		0x08<<3
+
+#define IR_HDLC			0x04
+#define IR_4PPM			0x01
+#define IR_CONSUMER		0x02
+
+#define CFG_B_LOOPBACK		0x01<<5
+#define CFG_B_LPBCK_TX_CRC	0x01<<4
+#define CFG_B_NOWAIT		0x01<<3
+#define CFB_B_STRING_MOVE	0x01<<2
+#define CFG_B_DMA_BURST 	0x01<<1
+#define CFG_B_DMA_ENABLE	0x01
+
+#define CFG_B_MUX_COM		0x00<<6
+#define CFG_B_MUX_IR		0x01<<6
+#define CFG_B_MUX_AUX		0x02<<6
+#define CFG_B_INACTIVE		0x03<<6
+
+/* Register block 2 - Consumer IR - not used */
+
+/* Register block 3 - Identification Registers! */
+
+#define SMSC_ID_HIGH	0x00   /* 0x10 */
+#define SMSC_ID_LOW	0x01   /* 0xB8 */
+#define CHIP_ID 	0x02   /* 0xF1 */
+#define VERSION_NUMBER	0x03   /* 0x01 */
+#define HOST_INTERFACE	0x04   /* low 4 = DMA, high 4 = IRQ */
+
+/* Register block 4 - IrDA */
+#define IR_CONTROL        0x00
+#define BOF_COUNT_LO      0x01
+#define BRICK_WALL_CNT_LO 0x02
+#define BRICK_TX_CNT_HI   0x03
+#define TX_DATA_SIZE_LO   0x04
+#define RX_DATA_SIZE_HI   0x05
+#define RX_DATA_SIZE_LO   0x06
+
+#define SELECT_1152     0x01<<7
+#define CRC_SELECT      0x01<<6
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/timer.h linux/include/net/irda/timer.h
--- v2.1.131/linux/include/net/irda/timer.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/timer.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,79 @@
+/*********************************************************************
+ *                
+ * Filename:      timer.h
+ * Version:       
+ * Description:   
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997, 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 TIMER_H
+#define TIMER_H
+
+#include "irda.h"
+#include "irmod.h"
+#include "irlap.h"
+#include "irlmp.h"
+#include "irda_device.h"
+
+/* 
+ *  Timeout definitions, some defined in IrLAP p. 92
+ */
+#define POLL_TIMEOUT        45             /* Must never exceed 500 ms */
+#define FINAL_TIMEOUT       50             /* Must never exceed 500 ms */
+
+/* 
+ *  Normally twice of p-timer. Note 3, IrLAP p. 60 suggests at least twice 
+ *  duration of the P-timer.
+ */
+#define WD_TIMEOUT          POLL_TIMEOUT*2
+#define MEDIABUSY_TIMEOUT   50             /* 500 msec */
+
+/*
+ *  Slot timer must never exceed 85 ms, and must always be at least 25 ms, 
+ *  suggested to  75-85 msec by IrDA lite
+ */
+#define SLOT_TIMEOUT             8
+#define QUERY_TIMEOUT          100
+
+#define WATCHDOG_TIMEOUT      2000                /* 20 sec */
+#define RETRY_TIMEOUT           51
+
+typedef void (*TIMER_CALLBACK)( unsigned long);
+
+void irda_start_timer( struct timer_list *ptimer, int timeout, int data,
+		       TIMER_CALLBACK callback);
+
+inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout);
+inline void irlap_start_query_timer( struct irlap_cb *self, int timeout);
+inline void irlap_start_final_timer( struct irlap_cb *self, int timeout);
+inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout);
+inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout);
+
+inline void irda_device_start_mbusy_timer( struct irda_device *self);
+
+struct lsap_cb;
+inline void irlmp_start_watchdog_timer( struct lsap_cb *, int timeout);
+inline void irlmp_start_discovery_timer( struct irlmp_cb *, int timeout); 
+
+struct irobex_cb;
+inline void irobex_start_watchdog_timer( struct irobex_cb *, int timeout);
+
+#endif
+
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/w83977af.h linux/include/net/irda/w83977af.h
--- v2.1.131/linux/include/net/irda/w83977af.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/w83977af.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,54 @@
+#ifndef W83977AF_H
+#define W83977AF_H
+
+#define W977_EFER 0x370
+#define W977_EFIR 0x370
+#define W977_EFDR 0x371
+#define W977_DEVICE_IR 0x06
+
+
+/*
+ * Enter extended function mode
+ */
+static inline void w977_efm_enter(void)
+{
+        outb(0x87, W977_EFER);
+        outb(0x87, W977_EFER);
+}
+
+/*
+ * Select a device to configure 
+ */
+
+static inline void w977_select_device(__u8 devnum)
+{
+	outb(0x07, W977_EFIR);
+	outb(devnum, W977_EFDR);
+} 
+
+/* 
+ * Write a byte to a register
+ */
+static inline void w977_write_reg(__u8 reg, __u8 value)
+{
+	outb(reg, W977_EFIR);
+	outb(value, W977_EFDR);
+}
+
+/*
+ * read a byte from a register
+ */
+static inline __u8 w977_read_reg(__u8 reg)
+{
+	outb(reg, W977_EFIR);
+	return inb(W977_EFDR);
+}
+
+/*
+ * Exit extended function mode
+ */
+static inline void w977_efm_exit(void)
+{
+	outb(0xAA, W977_EFER);
+}
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/w83977af_ir.h linux/include/net/irda/w83977af_ir.h
--- v2.1.131/linux/include/net/irda/w83977af_ir.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/w83977af_ir.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,158 @@
+/*********************************************************************
+ *                
+ * Filename:      w83977af_ir.h
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Paul VanderSpek
+ * Created at:    Thu Nov 19 13:55:34 1998
+ * Modified at:   Thu Dec 10 14:06:18 1998
+ * 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 W83977AF_IR_H
+#define W83977AF_IR_H
+
+#include <asm/io.h>
+
+/* Flags for configuration register CRF0 */
+#define ENBNKSEL	0x01
+#define APEDCRC		0x02
+#define TXW4C           0x04
+#define RXW4C           0x08
+
+/* Bank 0 */
+#define RBR             0x00 /* Receiver buffer register */
+#define TBR             0x00 /* Transmitter buffer register */
+
+#define ICR		0x01 /* Interrupt configuration register */
+#define ICR_ERBRI       0x01 /* Receiver buffer register interrupt */
+#define ICR_ETBREI      0x02 /* Transeiver empty interrupt */
+#define ICR_EUSRI	0x04//* IR status interrupt */
+#define ICR_EHSRI       0x04
+#define ICR_ETXURI      0x04 /* Tx underrun */
+#define ICR_EDMAI	0x10 /* DMA interrupt */
+#define ICR_ETXTHI      0x20 /* Transmitter threshold interrupt */
+#define ICR_EFSFI       0x40 /* Frame status FIFO interrupt */
+#define ICR_ETMRI       0x80 /* Timer interrupt */
+
+#define UFR		0x02 /* FIFO control register */
+#define UFR_EN_FIFO     0x01 /* Enable FIFO's */
+#define UFR_RXF_RST     0x02 /* Reset Rx FIFO */
+#define UFR_TXF_RST     0x04 /* Reset Tx FIFO */
+#define UFR_RXTL	0x80 /* Rx FIFO threshold (set to 16) */
+#define UFR_TXTL	0x20 /* Tx FIFO threshold (set to 17) */
+
+#define ISR		0x02 /* Interrupt status register */
+#define ISR_RXTH_I	0x01 /* Receive threshold interrupt */
+#define ISR_TXEMP_I     0x02 /* Transmitter empty interrupt */
+#define ISR_FEND_I	0x04
+#define ISR_DMA_I	0x10
+#define ISR_TXTH_I	0x20 /* Transmitter threshold interrupt */
+#define ISR_FSF_I       0x40
+#define ISR_TMR_I       0x80 /* Timer interrupt */
+
+#define UCR             0x03 /* Uart control register */
+#define UCR_DLS8        0x03 /* 8N1 */
+
+#define SSR 	        0x03 /* Sets select register */
+#define SET0 	        UCR_DLS8        /* Make sure we keep 8N1 */
+#define SET1	        (0x80|UCR_DLS8) /* Make sure we keep 8N1 */
+#define SET2	        0xE0
+#define SET3	        0xE4
+#define SET4	        0xE8
+#define SET5	        0xEC
+#define SET6	        0xF0
+#define SET7	        0xF4
+
+#define HCR		0x04
+#define HCR_MODE_MASK	~(0xD0)
+#define HCR_SIR         0x60
+#define HCR_MIR_576  	0x20	
+#define HCR_MIR_1152	0x80
+#define HCR_FIR		0xA0
+#define HCR_EN_DMA	0x04
+#define HCR_EN_IRQ	0x08
+#define HCR_TX_WT	0x08
+
+#define USR             0x05 /* IR status register */
+#define USR_RDR         0x01 /* Receive data ready */
+#define USR_TSRE        0x40 /* Transmitter empty? */
+
+#define AUDR            0x07
+#define AUDR_SFEND      0x08 /* Set a frame end */
+#define AUDR_RXBSY      0x20 /* Rx busy */
+#define AUDR_UNDR       0x40 /* Transeiver underrun */
+
+/* Set 2 */
+#define ABLL            0x00 /* Advanced baud rate divisor latch (low byte) */
+#define ABHL            0x01 /* Advanced baud rate divisor latch (high byte) */
+
+#define ADCR1		0x02
+#define ADCR1_ADV_SL	0x01	
+#define ADCR1_D_CHSW	0x08	/* the specs are wrong. its bit 3, not 4 */
+#define ADCR1_DMA_F	0x02
+
+#define ADCR2		0x04
+#define ADCR2_TXFS32	0x01
+#define ADCR2_RXFS32	0x04
+
+#define RXFDTH          0x07
+
+/* Set 3 */
+#define AUID		0x00
+
+/* Set 4 */
+#define TMRL            0x00 /* Timer value register (low byte) */
+#define TMRH            0x01 /* Timer value register (high byte) */
+
+#define IR_MSL          0x02 /* Infrared mode select */
+#define IR_MSL_EN_TMR   0x01 /* Enable timer */
+
+#define TFRLL		0x04 /* Transmitter frame length (low byte) */
+#define TFRLH		0x05 /* Transmitter frame length (high byte) */
+#define RFRLL		0x06 /* Receiver frame length (low byte) */
+#define RFRLH		0x07 /* Receiver frame length (high byte) */
+
+/* Set 5 */
+
+#define FS_FO           0x05 /* Frame status FIFO */
+#define FS_FO_FSFDR     0x80 /* Frame status FIFO data ready */
+#define FS_FO_LST_FR    0x40 /* Frame lost */
+#define FS_FO_MX_LEX    0x10 /* Max frame len exceeded */
+#define FS_FO_PHY_ERR   0x08 /* Physical layer error */
+#define FS_FO_CRC_ERR   0x04 
+#define FS_FO_RX_OV     0x02 /* Receive overrun */
+#define FS_FO_FSF_OV    0x01 /* Frame status FIFO overrun */
+#define FS_FO_ERR_MSK   0x5f /* Error mask */
+
+#define RFLFL           0x06
+#define RFLFH           0x07
+
+/* Set 6 */
+#define IR_CFG2		0x00
+#define IR_CFG2_DIS_CRC	0x02
+
+/* Set 7 */
+#define IRM_CR		0x07 /* Infrared module control register */
+#define IRM_CR_IRX_MSL	0x40
+#define IRM_CR_AF_MNT   0x80 /* Automatic format */
+
+static inline void switch_bank( int iobase, int set)
+{
+	outb( set, iobase+SSR);
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/net/irda/wrapper.h linux/include/net/irda/wrapper.h
--- v2.1.131/linux/include/net/irda/wrapper.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/wrapper.h	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,57 @@
+/*********************************************************************
+ *                
+ * Filename:      wrapper.h
+ * Version:       
+ * 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 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 WRAPPER_H
+#define WRAPPER_H
+
+#include <linux/types.h>
+#include <linux/skbuff.h>
+
+#include "irda_device.h"
+
+#define BOF  0xc0 /* Beginning of frame */
+#define XBOF 0xff
+#define EOF  0xc1 /* End of frame */
+#define CE   0x7d /* Control escape */
+
+#define STA BOF  /* Start flag */
+#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, 
+	BEGIN_FRAME, 
+	LINK_ESCAPE, 
+	INSIDE_FRAME
+};
+
+/* Proto definitions */
+int  async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize);
+void async_unwrap_char( struct irda_device *, __u8 byte);
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/include/video/fbcon.h linux/include/video/fbcon.h
--- v2.1.131/linux/include/video/fbcon.h	Thu Nov 19 09:56:29 1998
+++ linux/include/video/fbcon.h	Mon Dec 21 14:48:04 1998
@@ -100,6 +100,7 @@
 #define __SCROLL_YFIXED		0x010
 #define __SCROLL_YNOMOVE	0x020
 #define __SCROLL_YPANREDRAW	0x040
+#define __SCROLL_YNOPARTIAL	0x080
 
 /* Only these should be used by the drivers */
 /* Which one should you use? If you have a fast card and slow bus,
@@ -116,6 +117,15 @@
  */
 #define SCROLL_YREDRAW		(__SCROLL_YFIXED|__SCROLL_YREDRAW)
 #define SCROLL_YNOMOVE		(__SCROLL_YNOMOVE|__SCROLL_YPANREDRAW)
+
+/* SCROLL_YNOPARTIAL, used in combination with the above, is for video
+   cards which can not handle using panning to scroll a portion of the
+   screen without excessive flicker.  Panning will only be used for
+   whole screens.
+ */
+/* Namespace consistency */
+#define SCROLL_YNOPARTIAL	__SCROLL_YNOPARTIAL
+
 
 extern void fbcon_redraw_bmove(struct display *, int, int, int, int, int, int);
 
diff -u --recursive --new-file v2.1.131/linux/init/main.c linux/init/main.c
--- v2.1.131/linux/init/main.c	Wed Dec 16 10:32:56 1998
+++ linux/init/main.c	Fri Dec 18 09:33:39 1998
@@ -90,6 +90,7 @@
 extern void smp_setup(char *str, int *ints);
 #ifdef __i386__
 extern void ioapic_pirq_setup(char *str, int *ints);
+extern void ioapic_setup(char *str, int *ints);
 #endif
 extern void no_scroll(char *str, int *ints);
 extern void kbd_reset_setup(char *str, int *ints);
@@ -541,6 +542,7 @@
 	{ "nosmp", smp_setup },
 	{ "maxcpus=", smp_setup },
 #ifdef __i386__
+	{ "noapic", ioapic_setup },
 	{ "pirq=", ioapic_pirq_setup },
 #endif
 #endif
diff -u --recursive --new-file v2.1.131/linux/ipc/shm.c linux/ipc/shm.c
--- v2.1.131/linux/ipc/shm.c	Fri Nov 27 13:09:29 1998
+++ linux/ipc/shm.c	Fri Dec 18 09:37:22 1998
@@ -126,6 +126,8 @@
 	return (unsigned int) shp->u.shm_perm.seq * SHMMNI + id;
 }
 
+int shmmax = SHMMAX;
+
 asmlinkage int sys_shmget (key_t key, int size, int shmflg)
 {
 	struct shmid_kernel *shp;
@@ -133,7 +135,7 @@
 
 	down(&current->mm->mmap_sem);
 	lock_kernel();
-	if (size < 0 || size > SHMMAX) {
+	if (size < 0 || size > shmmax) {
 		err = -EINVAL;
 	} else if (key == IPC_PRIVATE) {
 		err = newseg(key, shmflg, size);
@@ -228,7 +230,7 @@
 		if (!buf)
 			goto out;
 		shminfo.shmmni = SHMMNI;
-		shminfo.shmmax = SHMMAX;
+		shminfo.shmmax = shmmax;
 		shminfo.shmmin = SHMMIN;
 		shminfo.shmall = SHMALL;
 		shminfo.shmseg = SHMSEG;
diff -u --recursive --new-file v2.1.131/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.1.131/linux/kernel/ksyms.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/ksyms.c	Fri Dec 18 07:09:36 1998
@@ -172,6 +172,9 @@
 EXPORT_SYMBOL(find_inode_number);
 EXPORT_SYMBOL(is_subdir);
 EXPORT_SYMBOL(get_unused_fd);
+EXPORT_SYMBOL(vfs_rmdir);
+EXPORT_SYMBOL(vfs_unlink);
+EXPORT_SYMBOL(vfs_rename);
 
 #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
 EXPORT_SYMBOL(do_nfsservctl);
diff -u --recursive --new-file v2.1.131/linux/kernel/signal.c linux/kernel/signal.c
--- v2.1.131/linux/kernel/signal.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/signal.c	Fri Dec 18 09:37:22 1998
@@ -28,8 +28,8 @@
 
 static kmem_cache_t *signal_queue_cachep;
 
-static int nr_queued_signals;
-static int max_queued_signals = 1024;
+int nr_queued_signals;
+int max_queued_signals = 1024;
 
 void __init signals_init(void)
 {
diff -u --recursive --new-file v2.1.131/linux/kernel/softirq.c linux/kernel/softirq.c
--- v2.1.131/linux/kernel/softirq.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/softirq.c	Mon Dec 21 21:09:15 1998
@@ -6,6 +6,9 @@
  * do_bottom_half() runs at normal kernel priority: all interrupts
  * enabled.  do_bottom_half() is atomic with respect to itself: a
  * bottom_half handler need not be re-entrant.
+ *
+ * Fixed a disable_bh()/enable_bh() race (was causing a console lockup)
+ * due bh_mask_count not atomic handling. Copyright (C) 1998  Andrea Arcangeli
  */
 
 #include <linux/mm.h>
@@ -17,7 +20,7 @@
 
 /* intr_count died a painless death... -DaveM */
 
-int bh_mask_count[32];
+atomic_t bh_mask_count[32];
 unsigned long bh_active = 0;
 unsigned long bh_mask = 0;
 void (*bh_base[32])(void);
diff -u --recursive --new-file v2.1.131/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.1.131/linux/kernel/sysctl.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/sysctl.c	Sun Dec 20 05:51:07 1998
@@ -216,6 +216,8 @@
 	 &pager_daemon, sizeof(pager_daemon_t), 0644, NULL, &proc_dointvec},
 	{VM_PGT_CACHE, "pagetable_cache", 
 	 &pgt_cache_water, 2*sizeof(int), 0600, NULL, &proc_dointvec},
+	{VM_PAGE_CLUSTER, "page-cluster", 
+	 &page_cluster, sizeof(int), 0600, NULL, &proc_dointvec},
 	{0}
 };
 
diff -u --recursive --new-file v2.1.131/linux/mm/filemap.c linux/mm/filemap.c
--- v2.1.131/linux/mm/filemap.c	Wed Dec 16 10:32:56 1998
+++ linux/mm/filemap.c	Mon Dec 21 21:51:23 1998
@@ -118,119 +118,67 @@
 	__free_page(page);
 }
 
-/*
- * Check whether we can free this page.
- */
-static inline int shrink_one_page(struct page *page, int gfp_mask)
-{
-	struct buffer_head *tmp, *bh;
-
-	if (PageLocked(page))
-		goto next;
-	if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
-		goto next;
-	/* First of all, regenerate the page's referenced bit
-         * from any buffers in the page
-	 */
-	bh = page->buffers;
-	if (bh) {
-		tmp = bh;
-		do {
-			if (buffer_touched(tmp)) {
-				clear_bit(BH_Touched, &tmp->b_state);
-				set_bit(PG_referenced, &page->flags);
-			}
-			tmp = tmp->b_this_page;
-		} while (tmp != bh);
-
-		/* Refuse to swap out all buffer pages */
-		if (buffer_under_min())
-			goto next;
-	}
-
-	/* We can't throw away shared pages, but we do mark
-	   them as referenced.  This relies on the fact that
-	   no page is currently in both the page cache and the
-	   buffer cache; we'd have to modify the following
-	   test to allow for that case. */
-
-	switch (atomic_read(&page->count)) {
-	case 1:
-		/* is it a swap-cache or page-cache page? */
-		if (page->inode) {
-			if (test_and_clear_bit(PG_referenced, &page->flags))
-				break;
-			if (pgcache_under_min())
-				break;
-			if (PageSwapCache(page)) {
-				delete_from_swap_cache(page);
-				return 1;
-			}
-			remove_inode_page(page);
-			return 1;
-		}
-		/* It's not a cache page, so we don't do aging.
-		 * If it has been referenced recently, don't free it */
-		if (test_and_clear_bit(PG_referenced, &page->flags))
-			break;
-
-		if (buffer_under_min())
-			break;
-
-		/* is it a buffer cache page? */
-		if (bh && try_to_free_buffer(bh, &bh, 6))
-			return 1;
-		break;
-
-	default:
-		/* more than one user: we can't throw it away */
-		set_bit(PG_referenced, &page->flags);
-		/* fall through */
-	case 0:
-		/* nothing */
-	}
-next:
-	return 0;
-}
-
 int shrink_mmap(int priority, int gfp_mask)
 {
 	static unsigned long clock = 0;
 	unsigned long limit = num_physpages;
 	struct page * page;
-	int count_max, count_min;
+	int count;
 
-	count_max = limit;
-	count_min = (limit<<2) >> (priority);
+	count = (limit<<1) >> (priority);
 
 	page = mem_map + clock;
 	do {
+		page++;
+		clock++;
+		if (clock >= max_mapnr) {
+			clock = 0;
+			page = mem_map;
+		}
 		if (PageSkip(page)) {
 			/* next_hash is overloaded for PageSkip */
 			page = page->next_hash;
 			clock = page->map_nr;
 		}
 		
-		if (shrink_one_page(page, gfp_mask))
+		if (test_and_clear_bit(PG_referenced, &page->flags))
+			continue;
+
+		/* Decrement count only for non-referenced pages */
+		count--;
+		if (PageLocked(page))
+			continue;
+
+		if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
+			continue;
+
+		/* We can't free pages unless there's just one user */
+		if (atomic_read(&page->count) != 1)
+			continue;
+
+		/* Is it a buffer page? */
+		if (page->buffers) {
+			struct buffer_head *bh = page->buffers;
+			if (buffer_under_min())
+				continue;
+			if (!try_to_free_buffer(bh, &bh))
+				continue;
 			return 1;
-		count_max--;
-		/* 
-		 * If the page we looked at was recyclable but we didn't
-		 * reclaim it (presumably due to PG_referenced), don't
-		 * count it as scanned.  This way, the more referenced
-		 * page cache pages we encounter, the more rapidly we
-		 * will age them. 
-		 */
-		if (atomic_read(&page->count) != 1 ||
-		    (!page->inode && !page->buffers))
-			count_min--;
-		page++;
-		clock++;
-		if (clock >= max_mapnr) {
-			clock = 0;
-			page = mem_map;
 		}
-	} while (count_max > 0 && count_min > 0);
+
+		/* is it a swap-cache or page-cache page? */
+		if (page->inode) {
+			if (pgcache_under_min())
+				continue;
+			if (PageSwapCache(page)) {
+				delete_from_swap_cache(page);
+				return 1;
+			}
+			remove_inode_page(page);
+			return 1;
+		}
+
+	} while (count > 0);
 	return 0;
 }
 
@@ -974,7 +922,7 @@
 	struct file * file = area->vm_file;
 	struct dentry * dentry = file->f_dentry;
 	struct inode * inode = dentry->d_inode;
-	unsigned long offset;
+	unsigned long offset, reada, i;
 	struct page * page, **hash;
 	unsigned long old_page, new_page;
 
@@ -1035,7 +983,18 @@
 	return new_page;
 
 no_cached_page:
-	new_page = __get_free_page(GFP_USER);
+	/*
+	 * Try to read in an entire cluster at once.
+	 */
+	reada   = offset;
+	reada >>= PAGE_SHIFT + page_cluster;
+	reada <<= PAGE_SHIFT + page_cluster;
+
+	for (i = 1 << page_cluster; i > 0; --i, reada += PAGE_SIZE)
+		new_page = try_to_read_ahead(file, reada, new_page);
+
+	if (!new_page)
+		new_page = __get_free_page(GFP_USER);
 	if (!new_page)
 		goto no_page;
 
@@ -1059,11 +1018,6 @@
 	if (inode->i_op->readpage(file, page) != 0)
 		goto failure;
 
-	/*
-	 * Do a very limited read-ahead if appropriate
-	 */
-	if (PageLocked(page))
-		new_page = try_to_read_ahead(file, offset + PAGE_SIZE, 0);
 	goto found_page;
 
 page_locked_wait:
@@ -1637,7 +1591,7 @@
 	if (!page) {
 		if (!new)
 			goto out;
-		page_cache = get_free_page(GFP_KERNEL);
+		page_cache = get_free_page(GFP_USER);
 		if (!page_cache)
 			goto out;
 		page = mem_map + MAP_NR(page_cache);
diff -u --recursive --new-file v2.1.131/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.1.131/linux/mm/page_alloc.c	Fri Nov 27 13:09:30 1998
+++ linux/mm/page_alloc.c	Sun Dec 20 05:51:07 1998
@@ -359,6 +359,38 @@
 	return start_mem;
 }
 
+/* 
+ * Primitive swap readahead code. We simply read an aligned block of
+ * (1 << page_cluster) entries in the swap area. This method is chosen
+ * because it doesn't cost us any seek time.  We also make sure to queue
+ * the 'original' request together with the readahead ones...  
+ */
+void swapin_readahead(unsigned long entry)
+{
+	int i;
+	struct page *new_page;
+	unsigned long offset = SWP_OFFSET(entry);
+	struct swap_info_struct *swapdev = SWP_TYPE(entry) + swap_info;
+	
+	offset = (offset >> page_cluster) << page_cluster;
+	
+	for (i = 1 << page_cluster; i > 0; i--) {
+	      if (offset >= swapdev->max
+			      || nr_free_pages - atomic_read(&nr_async_pages) <
+			      (freepages.high + freepages.low)/2)
+		      return;
+	      if (!swapdev->swap_map[offset] ||
+		  swapdev->swap_map[offset] == SWAP_MAP_BAD ||
+		  test_bit(offset, swapdev->swap_lockmap))
+		      continue;
+	      new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset), 0);
+	      if (new_page != NULL)
+		      __free_page(new_page);
+	      offset++;
+	}
+	return;
+}
+
 /*
  * The tests may look silly, but it essentially makes sure that
  * no other process did a swap-in on us just as we were waiting.
@@ -370,10 +402,12 @@
 	pte_t * page_table, unsigned long entry, int write_access)
 {
 	unsigned long page;
-	struct page *page_map;
-	
-	page_map = read_swap_cache(entry);
+	struct page *page_map = lookup_swap_cache(entry);
 
+	if (!page_map) {
+		swapin_readahead(entry);
+		page_map = read_swap_cache(entry);
+	}
 	if (pte_val(*page_table) != entry) {
 		if (page_map)
 			free_page_and_swap_cache(page_address(page_map));
diff -u --recursive --new-file v2.1.131/linux/mm/page_io.c linux/mm/page_io.c
--- v2.1.131/linux/mm/page_io.c	Fri Nov 27 13:09:30 1998
+++ linux/mm/page_io.c	Sun Dec 20 05:51:07 1998
@@ -60,7 +60,7 @@
 	}
 
 	/* Don't allow too many pending pages in flight.. */
-	if (atomic_read(&nr_async_pages) > SWAP_CLUSTER_MAX)
+	if (atomic_read(&nr_async_pages) > pager_daemon.swap_cluster)
 		wait = 1;
 
 	p = &swap_info[type];
diff -u --recursive --new-file v2.1.131/linux/mm/swap.c linux/mm/swap.c
--- v2.1.131/linux/mm/swap.c	Wed Dec 16 10:32:56 1998
+++ linux/mm/swap.c	Sun Dec 20 05:51:07 1998
@@ -39,6 +39,9 @@
 	144	/* freepages.high */
 };
 
+/* How many pages do we try to swap or page in/out together? */
+int page_cluster = 4; /* Default value modified in swap_setup() */
+
 /* We track the number of pages currently being asynchronously swapped
    out, so that we don't try to swap TOO many pages out at once */
 atomic_t nr_async_pages = ATOMIC_INIT(0);
@@ -77,3 +80,19 @@
 	SWAP_CLUSTER_MAX,	/* minimum number of tries */
 	SWAP_CLUSTER_MAX,	/* do swap I/O in clusters of this size */
 };
+
+
+/*
+ * Perform any setup for the swap system
+ */
+
+void __init swap_setup(void)
+{
+	/* Use a smaller cluster for memory <16MB or <32MB */
+	if (num_physpages < ((16 * 1024 * 1024) >> PAGE_SHIFT))
+		page_cluster = 2;
+	else if (num_physpages < ((32 * 1024 * 1024) >> PAGE_SHIFT))
+		page_cluster = 3;
+	else
+		page_cluster = 4;
+}
diff -u --recursive --new-file v2.1.131/linux/mm/swap_state.c linux/mm/swap_state.c
--- v2.1.131/linux/mm/swap_state.c	Fri Nov 27 13:09:30 1998
+++ linux/mm/swap_state.c	Sun Dec 20 05:51:07 1998
@@ -258,7 +258,7 @@
  * incremented.
  */
 
-static struct page * lookup_swap_cache(unsigned long entry)
+struct page * lookup_swap_cache(unsigned long entry)
 {
 	struct page *found;
 	
@@ -305,7 +305,7 @@
 	if (found_page)
 		goto out;
 
-	new_page_addr = __get_free_page(GFP_KERNEL);
+	new_page_addr = __get_free_page(GFP_USER);
 	if (!new_page_addr)
 		goto out;	/* Out of memory */
 	new_page = mem_map + MAP_NR(new_page_addr);
diff -u --recursive --new-file v2.1.131/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.1.131/linux/mm/vmscan.c	Wed Dec 16 10:32:56 1998
+++ linux/mm/vmscan.c	Tue Dec 22 13:04:24 1998
@@ -418,45 +418,6 @@
 }
 
 /*
- * We are much more aggressive about trying to swap out than we used
- * to be.  This works out OK, because we now do proper aging on page
- * contents. 
- */
-static int do_try_to_free_page(int gfp_mask)
-{
-	static int state = 0;
-	int i=6;
-
-	/* Always trim SLAB caches when memory gets low. */
-	kmem_cache_reap(gfp_mask);
-
-	if (buffer_over_borrow() || pgcache_over_borrow())
-		state = 0;
-
-	switch (state) {
-		do {
-		case 0:
-			if (shrink_mmap(i, gfp_mask))
-				return 1;
-			state = 1;
-		case 1:
-			if (shm_swap(i, gfp_mask))
-				return 1;
-			state = 2;
-		case 2:
-			if (swap_out(i, gfp_mask))
-				return 1;
-			state = 3;
-		case 3:
-			shrink_dcache_memory(i, gfp_mask);
-			state = 0;
-		i--;
-		} while (i >= 0);
-	}
-	return 0;
-}
-
-/*
  * Before we start the kernel thread, print out the 
  * kswapd initialization message (otherwise the init message 
  * may be printed in the middle of another driver's init 
@@ -467,6 +428,8 @@
        int i;
        char *revision="$Revision: 1.5 $", *s, *e;
 
+       swap_setup();
+       
        if ((s = strchr(revision, ':')) &&
            (e = strchr(s, '$')))
                s++, i = e - s;
@@ -475,6 +438,44 @@
        printk ("Starting kswapd v%.*s\n", i, s);
 }
 
+#define free_memory(fn) \
+	count++; do { if (!--count) goto done; } while (fn)
+
+static int kswapd_free_pages(int kswapd_state)
+{
+	unsigned long end_time;
+
+	/* Always trim SLAB caches when memory gets low. */
+	kmem_cache_reap(0);
+
+	/* max one hundreth of a second */
+	end_time = jiffies + (HZ-1)/100;
+	do {
+		int priority = 5;
+		int count = pager_daemon.swap_cluster;
+
+		switch (kswapd_state) {
+			do {
+			default:
+				free_memory(shrink_mmap(priority, 0));
+				kswapd_state++;
+			case 1:
+				free_memory(shm_swap(priority, 0));
+				kswapd_state++;
+			case 2:
+				free_memory(swap_out(priority, 0));
+				shrink_dcache_memory(priority, 0);
+				kswapd_state = 0;
+			} while (--priority >= 0);
+			return kswapd_state;
+		}
+done:
+		if (nr_free_pages > freepages.high + pager_daemon.swap_cluster)
+			break;
+	} while (time_before_eq(jiffies,end_time));
+	return kswapd_state;
+}
+
 /*
  * The background pageout daemon.
  * Started as a kernel thread from the init process.
@@ -517,22 +518,14 @@
 	init_swap_timer();
 	kswapd_task = current;
 	while (1) {
-		unsigned long end_time;
+		int state = 0;
 
 		current->state = TASK_INTERRUPTIBLE;
 		flush_signals(current);
 		run_task_queue(&tq_disk);
 		schedule();
 		swapstats.wakeups++;
-
-		/* max one hundreth of a second */
-		end_time = jiffies + (HZ-1)/100;
-		do {
-			if (!do_try_to_free_page(0))
-				break;
-			if (nr_free_pages > freepages.high + SWAP_CLUSTER_MAX)
-				break;
-		} while (time_before_eq(jiffies,end_time));
+		state = kswapd_free_pages(state);
 	}
 	/* As if we could ever get here - maybe we want to make this killable */
 	kswapd_task = NULL;
@@ -549,23 +542,39 @@
  * if we need more memory as part of a swap-out effort we
  * will just silently return "success" to tell the page
  * allocator to accept the allocation.
+ *
+ * We want to try to free "count" pages, and we need to 
+ * cluster them so that we get good swap-out behaviour. See
+ * the "free_memory()" macro for details.
  */
 int try_to_free_pages(unsigned int gfp_mask, int count)
 {
-	int retval = 1;
+	int retval;
 
 	lock_kernel();
+
+	/* Always trim SLAB caches when memory gets low. */
+	kmem_cache_reap(gfp_mask);
+
+	retval = 1;
 	if (!(current->flags & PF_MEMALLOC)) {
+		int priority;
+
 		current->flags |= PF_MEMALLOC;
+	
+		priority = 5;
 		do {
-			retval = do_try_to_free_page(gfp_mask);
-			if (!retval)
-				break;
-			count--;
-		} while (count > 0);
+			free_memory(shrink_mmap(priority, gfp_mask));
+			free_memory(shm_swap(priority, gfp_mask));
+			free_memory(swap_out(priority, gfp_mask));
+			shrink_dcache_memory(priority, gfp_mask);
+		} while (--priority >= 0);
+		retval = 0;
+done:
 		current->flags &= ~PF_MEMALLOC;
 	}
 	unlock_kernel();
+
 	return retval;
 }
 
diff -u --recursive --new-file v2.1.131/linux/net/802/tr.c linux/net/802/tr.c
--- v2.1.131/linux/net/802/tr.c	Thu Jul 16 18:09:32 1998
+++ linux/net/802/tr.c	Wed Dec 16 13:35:50 1998
@@ -154,10 +154,12 @@
 		return 0;
 	}
 
+#ifdef CONFIG_INET
 	if(arp_find(trh->daddr, skb)) {
 			return 1;
 	}
 	else 
+#endif	
 	{	
 		tr_source_route(skb,trh,dev); 
 		return 0;
diff -u --recursive --new-file v2.1.131/linux/net/Makefile linux/net/Makefile
--- v2.1.131/linux/net/Makefile	Tue Jul 28 14:21:10 1998
+++ linux/net/Makefile	Thu Dec 17 09:03:57 1998
@@ -10,7 +10,7 @@
 MOD_SUB_DIRS := ipv4
 ALL_SUB_DIRS := 802 ax25 bridge core ethernet ipv4 ipv6 ipx unix appletalk \
 		netrom rose lapb x25 wanrouter netlink sched packet sunrpc \
-		econet #decnet
+		econet irda #decnet
 SUB_DIRS     := core ethernet sched
 MOD_LIST_NAME := NET_MISC_MODULES
 
@@ -125,6 +125,14 @@
   endif
 endif
 
+ifeq ($(CONFIG_IRDA),y)
+SUB_DIRS += irda
+else
+  ifeq ($(CONFIG_IRDA),m)
+  MOD_SUB_DIRS += irda
+  endif
+endif
+
 ifeq ($(CONFIG_SUNRPC),y)
 SUB_DIRS += sunrpc
 else
@@ -168,7 +176,9 @@
 M_OBJS	     :=
 
 ifeq ($(CONFIG_SYSCTL),y)
+ifeq ($(CONFIG_NET),y)
 L_OBJS += sysctl_net.o
+endif
 endif
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.1.131/linux/net/appletalk/ddp.c linux/net/appletalk/ddp.c
--- v2.1.131/linux/net/appletalk/ddp.c	Thu Nov 19 09:56:29 1998
+++ linux/net/appletalk/ddp.c	Thu Dec 17 09:07:45 1998
@@ -912,7 +912,7 @@
 			break;			
 
 		case SIOCSARP:
-			if(!suser())
+			if(!capable(CAP_NET_ADMIN))
                                 return (-EPERM);
                         if(sa->sat_family != AF_APPLETALK)
                                 return (-EINVAL);
@@ -961,7 +961,7 @@
                         break;
 
                 case SIOCDARP:
-                        if(!suser())
+                        if(!capable(CAP_NET_ADMIN))
                                 return (-EPERM);
                         if(sa->sat_family != AF_APPLETALK)
                                 return (-EINVAL);
diff -u --recursive --new-file v2.1.131/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.1.131/linux/net/ax25/af_ax25.c	Thu Sep 17 17:53:39 1998
+++ linux/net/ax25/af_ax25.c	Fri Dec 18 13:56:21 1998
@@ -1242,21 +1242,17 @@
 		return -EINVAL;
 
 	/*
-	 *	The write queue this time is holding sockets ready to use
+	 *	The read 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();
+			if (flags & O_NONBLOCK)
 				return -EWOULDBLOCK;
-			}
+
 			interruptible_sleep_on(sk->sleep);
-			if (signal_pending(current)) {
-				sti();
+			if (signal_pending(current)) 
 				return -ERESTARTSYS;
-			}
 		}
 	} while (skb == NULL);
 
@@ -1264,10 +1260,10 @@
 	newsk->pair = NULL;
 	newsk->socket = newsock;
 	newsk->sleep = &newsock->wait;
-	sti();
 
 	/* Now attach up the new socket */
 	skb->sk = NULL;
+	skb->destructor = NULL;
 	kfree_skb(skb);
 	sk->ack_backlog--;
 	newsock->sk    = newsk;
diff -u --recursive --new-file v2.1.131/linux/net/ax25/ax25_ds_in.c linux/net/ax25/ax25_ds_in.c
--- v2.1.131/linux/net/ax25/ax25_ds_in.c	Mon Jul  7 08:19:59 1997
+++ linux/net/ax25/ax25_ds_in.c	Fri Dec 18 13:56:21 1998
@@ -19,6 +19,7 @@
  *	AX.25 036	Jonathan(G4KLX)	Cloned from ax25_in.c
  *			Joerg(DL1BKE)	Fixed it.
  *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
+ *			Joerg(DL1BKE)	ax25->n2count never got reset
  */
 
 #include <linux/config.h>
@@ -47,7 +48,7 @@
 
 /*
  *	State machine for state 1, Awaiting Connection State.
- *	The handling of the timer(s) is in file ax25_timer.c.
+ *	The handling of the timer(s) is in file ax25_ds_timer.c.
  *	Handling of state 0 and connection release is in ax25.c.
  */
 static int ax25_ds_state1_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
@@ -58,6 +59,12 @@
 			ax25->window  = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
 			break;
+			
+		case AX25_SABME:
+			ax25->modulus = AX25_EMODULUS;
+			ax25->window  =  ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
+			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
+			break;
 
 		case AX25_DISC:
 			ax25_send_control(ax25, AX25_DM, pf, AX25_RESPONSE);
@@ -83,7 +90,7 @@
 
 			/* according to DK4EGŽs spec we are required to
 			 * send a RR RESPONSE FINAL NR=0. Please mail
-			 * <jr@lykos.oche.de> if this causes problems
+			 * <jreuter@poboxes.com> if this causes problems
 			 * with the TheNetNode DAMA Master implementation.
 			 */ 
 
@@ -104,13 +111,14 @@
 
 /*
  *	State machine for state 2, Awaiting Release State.
- *	The handling of the timer(s) is in file ax25_timer.c
+ *	The handling of the timer(s) is in file ax25_ds_timer.c
  *	Handling of state 0 and connection release is in ax25.c.
  */
 static int ax25_ds_state2_machine(ax25_cb *ax25, struct sk_buff *skb, int frametype, int pf, int type)
 {
 	switch (frametype) {
 		case AX25_SABM:
+		case AX25_SABME:
 			ax25_send_control(ax25, AX25_DISC, AX25_POLLON, AX25_COMMAND);
 			ax25_dama_off(ax25);
 			break;
@@ -157,8 +165,14 @@
 
 	switch (frametype) {
 		case AX25_SABM:
-			ax25->modulus   = AX25_MODULUS;
-			ax25->window    = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
+		case AX25_SABME:
+			if (frametype == AX25_SABM) {
+				ax25->modulus   = AX25_MODULUS;
+				ax25->window    = ax25->ax25_dev->values[AX25_VALUES_WINDOW];
+			} else {
+				ax25->modulus   = AX25_EMODULUS;
+				ax25->window    = ax25->ax25_dev->values[AX25_VALUES_EWINDOW];
+			}
 			ax25_send_control(ax25, AX25_UA, pf, AX25_RESPONSE);
 			ax25_stop_t1timer(ax25);
 			ax25_start_t3timer(ax25);
@@ -188,8 +202,10 @@
 				ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
 			else
 				ax25->condition |= AX25_COND_PEER_RX_BUSY;
+
 			if (ax25_validate_nr(ax25, nr)) {
-				ax25_check_iframes_acked(ax25, nr);
+				if (ax25_check_iframes_acked(ax25, nr))
+					ax25->n2count=0;
 				if (type == AX25_COMMAND && pf)
 					ax25_ds_enquiry_response(ax25);
 			} else {
@@ -200,13 +216,17 @@
 
 		case AX25_REJ:
 			ax25->condition &= ~AX25_COND_PEER_RX_BUSY;
+
 			if (ax25_validate_nr(ax25, nr)) {
+				if (ax25->va != nr)
+					ax25->n2count=0;
+
 				ax25_frames_acked(ax25, nr);
 				ax25_calculate_rtt(ax25);
 				ax25_stop_t1timer(ax25);
 				ax25_start_t3timer(ax25);
-				ax25->n2count = 0;
 				ax25_requeue_frames(ax25);
+
 				if (type == AX25_COMMAND && pf)
 					ax25_ds_enquiry_response(ax25);
 			} else {
@@ -225,14 +245,15 @@
 				ax25_frames_acked(ax25, nr);
 				ax25->n2count = 0;
 			} else {
-				ax25_check_iframes_acked(ax25, nr);
+				if (ax25_check_iframes_acked(ax25, nr))
+					ax25->n2count = 0;
 			}
 			if (ax25->condition & AX25_COND_OWN_RX_BUSY) {
 				if (pf) ax25_ds_enquiry_response(ax25);
 				break;
 			}
 			if (ns == ax25->vr) {
-				ax25->vr = (ax25->vr + 1) % AX25_MODULUS;
+				ax25->vr = (ax25->vr + 1) % ax25->modulus;
 				queued = ax25_rx_iframe(ax25, skb);
 				if (ax25->condition & AX25_COND_OWN_RX_BUSY)
 					ax25->vr = ns;	/* ax25->vr - 1 */
diff -u --recursive --new-file v2.1.131/linux/net/ax25/ax25_ds_timer.c linux/net/ax25/ax25_ds_timer.c
--- v2.1.131/linux/net/ax25/ax25_ds_timer.c	Mon Jul  7 08:19:59 1997
+++ linux/net/ax25/ax25_ds_timer.c	Fri Dec 18 13:56:21 1998
@@ -119,8 +119,10 @@
 			 * Check the state of the receive buffer.
 			 */
 			if (ax25->sk != NULL) {
-				if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) && (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
+				if (atomic_read(&ax25->sk->rmem_alloc) < (ax25->sk->rcvbuf / 2) && 
+				    (ax25->condition & AX25_COND_OWN_RX_BUSY)) {
 					ax25->condition &= ~AX25_COND_OWN_RX_BUSY;
+					ax25->condition &= ~AX25_COND_ACK_PENDING;
 					break;
 				}
 			}
@@ -150,17 +152,11 @@
 	ax25_clear_queues(ax25);
 
 	ax25->n2count = 0;
-
-	/* state 1 or 2 should not happen, but... */
-
-	if (ax25->state == AX25_STATE_1 || ax25->state == AX25_STATE_2)
-		ax25->state = AX25_STATE_0;
-	else
-		ax25->state = AX25_STATE_2;
+	ax25->state = AX25_STATE_2;
 
 	ax25_calculate_t1(ax25);
 	ax25_start_t1timer(ax25);
-	ax25_start_t3timer(ax25);
+	ax25_stop_t3timer(ax25);
 
 	if (ax25->sk != NULL) {
 		ax25->sk->state     = TCP_CLOSE;
diff -u --recursive --new-file v2.1.131/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.1.131/linux/net/ax25/ax25_in.c	Thu Feb 12 20:56:14 1998
+++ linux/net/ax25/ax25_in.c	Fri Dec 18 13:56:21 1998
@@ -389,10 +389,9 @@
 		}
 
 		ax25 = make->protinfo.ax25;
-
+		skb_set_owner_r(skb, make);
 		skb_queue_head(&sk->receive_queue, skb);
 
-		skb->sk     = make;
 		make->state = TCP_ESTABLISHED;
 		make->pair  = sk;
 
@@ -473,6 +472,7 @@
 int ax25_kiss_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *ptype)
 {
 	skb->sk = NULL;		/* Initially we don't know who it's for */
+	skb->destructor = NULL;	/* Who initializes this, dammit?! */
 
 	if ((*skb->data & 0x0F) != 0) {
 		kfree_skb(skb);	/* Not a KISS data frame */
diff -u --recursive --new-file v2.1.131/linux/net/ax25/ax25_out.c linux/net/ax25/ax25_out.c
--- v2.1.131/linux/net/ax25/ax25_out.c	Sun Jul 26 11:57:20 1998
+++ linux/net/ax25/ax25_out.c	Fri Dec 18 13:56:21 1998
@@ -30,6 +30,8 @@
  *			Joerg(DL1BKE)	Fixed DAMA Slave mode: will work
  *					on non-DAMA interfaces like AX25L2V2
  *					again (this behaviour is _required_).
+ *			Joerg(DL1BKE)	ax25_check_iframes_acked() returns a 
+ *					value now (for DAMA n2count handling)
  */
 
 #include <linux/config.h>
@@ -391,20 +393,23 @@
 	dev_queue_xmit(skb);
 }
 
-void ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
+int ax25_check_iframes_acked(ax25_cb *ax25, unsigned short nr)
 {
 	if (ax25->vs == nr) {
 		ax25_frames_acked(ax25, nr);
 		ax25_calculate_rtt(ax25);
 		ax25_stop_t1timer(ax25);
 		ax25_start_t3timer(ax25);
+		return 1;
 	} else {
 		if (ax25->va != nr) {
 			ax25_frames_acked(ax25, nr);
 			ax25_calculate_t1(ax25);
 			ax25_start_t1timer(ax25);
+			return 1;
 		}
 	}
+	return 0;
 }
 
 #endif
diff -u --recursive --new-file v2.1.131/linux/net/bridge/br.c linux/net/bridge/br.c
--- v2.1.131/linux/net/bridge/br.c	Wed Apr  1 20:11:55 1998
+++ linux/net/bridge/br.c	Thu Dec 17 09:07:45 1998
@@ -50,6 +50,7 @@
  *	
  */
  
+#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -71,6 +72,7 @@
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <net/br.h>
+#include <linux/proc_fs.h>
 
 #ifndef min
 #define min(a, b) (((a) <= (b)) ? (a) : (b))
@@ -802,6 +804,40 @@
 	}					  /* (4.6.1.2.3)	 */
 }
 
+/* Vova Oksman: Write the buffer (contents of the Bridge table) */
+/* to a PROCfs file                                             */
+int br_tree_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
+{
+	int size;
+	int len=0;
+	off_t pos=0;
+	char* pbuffer;
+
+	if(0==offset)
+	{
+		/* first time write the header */
+		size = sprintf(buffer,"%s","MAC address           Device     Flags     Age (sec.)\n");
+		len=size;
+	}
+
+	pbuffer=&buffer[len];
+	sprintf_avl(&pbuffer,NULL,&pos,&len,offset,length);
+
+	*start = buffer+len-(pos-offset);	/* Start of wanted data */
+	len = pos-offset;			/* Start slop */
+	if (len>length)
+		len = length;			/* Ending slop */
+
+	return len;
+}
+#ifdef CONFIG_PROC_FS
+struct proc_dir_entry proc_net_bridge= {
+	PROC_NET_BRIDGE, 6, "bridge",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, &proc_net_inode_operations,
+	br_tree_get_info
+};
+#endif
 __initfunc(void br_init(void))
 {						  /* (4.8.1)	 */
 	int port_no;
@@ -857,6 +893,10 @@
 	br_stats.policy = BR_ACCEPT;			/* Enable bridge to accpet all protocols */
 	br_stats.exempt_protocols = 0;
 	/*start_hello_timer();*/
+	/* Vova Oksman: register the function for the PROCfs "bridge" file */
+#ifdef CONFIG_PROC_FS
+	proc_net_register(&proc_net_bridge);
+#endif
 }
 
 static inline unsigned short make_port_id(int port_no)
diff -u --recursive --new-file v2.1.131/linux/net/bridge/br_tree.c linux/net/bridge/br_tree.c
--- v2.1.131/linux/net/bridge/br_tree.c	Wed Apr  1 20:11:55 1998
+++ linux/net/bridge/br_tree.c	Thu Dec 17 09:07:45 1998
@@ -426,3 +426,46 @@
 	return(0);
 }
 
+/* Vova Oksman: function for copy tree to the buffer */
+void sprintf_avl (char **pbuffer, struct fdb * tree, off_t *pos,
+					int* len, off_t offset, int length)
+{
+	int size;
+
+	if( 0 == *pos){
+		if(avl_br_empty == tree)
+		/* begin from the root */
+			tree = fhp;
+		*pos = *len;
+	}
+
+	if (*pos >= offset+length)
+		return;
+
+	if (tree != avl_br_empty) {
+		/* don't write the local device */
+		if(tree->port != 0){
+			size = sprintf(*pbuffer,
+				   "%02x:%02x:%02x:%02x:%02x:%02x     eth%d       %d         %d\n",
+				   tree->ula[0],tree->ula[1],tree->ula[2],
+				   tree->ula[3],tree->ula[4],tree->ula[5], 
+				   tree->port-1, tree->flags,CURRENT_TIME-tree->timer);
+
+			(*pos)+=size;
+			(*len)+=size;
+			(*pbuffer)+=size;
+		}
+		if (*pos <= offset)
+			*len=0;
+
+		if (tree->fdb_avl_left != avl_br_empty) {
+			sprintf_avl (pbuffer,tree->fdb_avl_left,pos,len,offset,length);
+		}
+		if (tree->fdb_avl_right != avl_br_empty) {
+			sprintf_avl (pbuffer,tree->fdb_avl_right,pos,len,offset,length);
+		}
+
+	}
+
+	return;
+}
diff -u --recursive --new-file v2.1.131/linux/net/core/dev.c linux/net/core/dev.c
--- v2.1.131/linux/net/core/dev.c	Sun Nov  8 14:03:13 1998
+++ linux/net/core/dev.c	Fri Dec 18 09:37:41 1998
@@ -1897,9 +1897,6 @@
 	 * Some devices want to be initialized early..
 	 */
 
-#if defined(CONFIG_LANCE)
-	lance_init();
-#endif
 #if defined(CONFIG_SCC)
 	scc_init();
 #endif
@@ -1937,11 +1934,14 @@
 	 *	SLHC if present needs attaching so other people see it
 	 *	even if not opened.
 	 */
+	 
+#ifdef CONFIG_INET	 
 #if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
 	 || defined(CONFIG_PPP) \
     || (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
 	slhc_install();
 #endif	
+#endif
 
 #ifdef CONFIG_NET_PROFILE
 	net_profile_init();
diff -u --recursive --new-file v2.1.131/linux/net/decnet/README linux/net/decnet/README
--- v2.1.131/linux/net/decnet/README	Thu Sep  4 13:25:28 1997
+++ linux/net/decnet/README	Thu Dec 17 09:07:45 1998
@@ -4,10 +4,9 @@
 For information on the Linux DECnet Project and the latest progress,
 look at the project home page:
 
-http://eeshack3.swan.ac.uk/~gw7rrm/DECnet/index.html
+http://www-sigproc.eng.cam.ac.uk/~sjw44/
 
 To contribute either mail <SteveW@ACM.org> or post on one of the Linux
 mailing lists (either linux-net or netdev).
 
 Steve Whitehouse <SteveW@ACM.org>
-http://eeshack3.swan.ac.uk/~gw7rrm
diff -u --recursive --new-file v2.1.131/linux/net/ipv4/icmp.c linux/net/ipv4/icmp.c
--- v2.1.131/linux/net/ipv4/icmp.c	Sun Nov  8 14:03:14 1998
+++ linux/net/ipv4/icmp.c	Fri Dec 18 09:35:22 1998
@@ -50,6 +50,8 @@
  *		Yu Tianli	:	Fixed two ugly bugs in icmp_send
  *					- IP option length was accounted wrongly
  *					- ICMP header length was not accounted at all.
+ *              Tristan Greaves :       Added sysctl option to ignore bogus broadcast
+ *                                      responses from broken routers.
  *
  * To Fix:
  *
@@ -311,6 +313,9 @@
 int sysctl_icmp_echo_ignore_all = 0;
 int sysctl_icmp_echo_ignore_broadcasts = 0;
 
+/* Control parameter - ignore bogus broadcast responses? */
+int sysctl_icmp_ignore_bogus_error_responses =0;
+
 /*
  *	ICMP control array. This specifies what to do with each ICMP.
  */
@@ -701,16 +706,19 @@
 	 *	first check your netmask matches at both ends, if it does then
 	 *	get the other vendor to fix their kit.
 	 */
-	 
-	if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
+
+	if (!sysctl_icmp_ignore_bogus_error_responses)
 	{
-		if (net_ratelimit())
-			printk(KERN_WARNING "%s sent an invalid ICMP error to a broadcast.\n",
-			       in_ntoa(skb->nh.iph->saddr));
-		return; 
+	
+		if (inet_addr_type(iph->daddr) == RTN_BROADCAST)
+		{
+			if (net_ratelimit())
+				printk(KERN_WARNING "%s sent an invalid ICMP error to a broadcast.\n",
+			       	in_ntoa(skb->nh.iph->saddr));
+			return; 
+		}
 	}
 
-
 	/*
 	 *	Deliver ICMP message to raw sockets. Pretty useless feature?
 	 */
@@ -886,8 +894,10 @@
 
 static void icmp_address(struct icmphdr *icmph, struct sk_buff *skb, int len)
 {
+#if 0
 	if (net_ratelimit())
 		printk(KERN_DEBUG "a guy asks for address mask. Who is it?\n");
+#endif		
 }
 
 /*
diff -u --recursive --new-file v2.1.131/linux/net/ipv4/sysctl_net_ipv4.c linux/net/ipv4/sysctl_net_ipv4.c
--- v2.1.131/linux/net/ipv4/sysctl_net_ipv4.c	Sun Nov  8 14:03:14 1998
+++ linux/net/ipv4/sysctl_net_ipv4.c	Fri Dec 18 09:35:22 1998
@@ -31,6 +31,7 @@
 /* From icmp.c */
 extern int sysctl_icmp_echo_ignore_all;
 extern int sysctl_icmp_echo_ignore_broadcasts;
+extern int sysctl_icmp_ignore_bogus_error_responses;
 
 /* From ip_fragment.c */
 extern int sysctl_ipfrag_low_thresh;
@@ -163,6 +164,9 @@
 	 &proc_dointvec},
 	{NET_IPV4_ICMP_ECHO_IGNORE_BROADCASTS, "icmp_echo_ignore_broadcasts",
 	 &sysctl_icmp_echo_ignore_broadcasts, sizeof(int), 0644, NULL,
+	 &proc_dointvec},
+	{NET_IPV4_ICMP_IGNORE_BOGUS_ERROR_RESPONSES, "icmp_ignore_bogus_error_responses",
+	 &sysctl_icmp_ignore_bogus_error_responses, sizeof(int), 0644, NULL,
 	 &proc_dointvec},
 	{NET_IPV4_ICMP_DESTUNREACH_RATE, "icmp_destunreach_rate",
 	 &sysctl_icmp_destunreach_time, sizeof(int), 0644, NULL, &proc_dointvec},
diff -u --recursive --new-file v2.1.131/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.1.131/linux/net/irda/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/Config.in	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,35 @@
+#
+# IrDA protocol configuration
+#
+
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  if [ "$CONFIG_NET" != "n" ] ; then
+
+    mainmenu_option next_comment
+    comment 'IrDA subsystem support'
+    dep_tristate 'IrDA subsystem support' CONFIG_IRDA $CONFIG_EXPERIMENTAL $CONFIG_NET
+
+    if [ "$CONFIG_IRDA" != "n" ] ; then
+      comment 'IrDA protocols'
+      source net/irda/irlan/Config.in
+      source net/irda/irobex/Config.in
+      source net/irda/ircomm/Config.in
+
+      bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
+      if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
+        comment '   IrDA options'
+        bool '   Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
+	bool '   Fast RRs' CONFIG_IRDA_FAST_RR
+        bool '   Recycle RRs' CONFIG_IRDA_RECYCLE_RR
+      fi
+    fi
+
+    if [ "$CONFIG_IRDA" != "n" ] ; then
+      source net/irda/compressors/Config.in
+      source drivers/net/irda/Config.in
+    fi
+  endmenu
+
+  fi
+fi
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/Makefile linux/net/irda/Makefile
--- v2.1.131/linux/net/irda/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/Makefile	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,80 @@
+#
+# Makefile for the Linux IrDA protocol layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+ALL_SUB_DIRS := irlan ircomm compressors
+SUB_DIRS :=
+MOD_SUB_DIRS :=
+
+O_TARGET := irda.o
+O_OBJS	 := irmod.o 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
+MOD_LIST_NAME := IRDA_MODULES
+M_OBJS   := $(O_TARGET)
+
+ifeq ($(CONFIG_IRDA_COMPRESSION),y)
+O_OBJS += irlap_comp.o
+endif
+
+ifeq ($(CONFIG_PROC_FS),y)
+O_OBJS += irproc.o
+endif
+
+ifeq ($(CONFIG_SYSCTL),y)
+O_OBJS += irsysctl.o
+endif
+
+ifeq ($(CONFIG_IRLAN),y)
+SUB_DIRS += irlan
+O_OBJS += irlan/irlan.o
+else
+  ifeq ($(CONFIG_IRLAN),m)
+  MOD_SUB_DIRS += irlan
+  endif
+endif
+
+ifeq ($(CONFIG_IROBEX),y)
+SUB_DIRS += irobex
+O_OBJS += irobex/irobex.o
+else
+  ifeq ($(CONFIG_IROBEX),m)
+  MOD_SUB_DIRS += irobex
+  endif
+endif
+
+ifeq ($(CONFIG_IRDA_COMPRESSION),y)
+SUB_DIRS += compressors
+MOD_IN_SUB_DIRS += compressors
+endif
+
+ifeq ($(CONFIG_IRDA_DEFLATE),y)
+O_OBJS += compressors/irda_deflate.o
+else
+  ifeq ($(CONFIG_IRDA_DEFLATE),m)
+  MOD_TO_LIST += irda_deflate.o
+  endif
+endif
+
+ifeq ($(CONFIG_IRCOMM),y)
+SUB_DIRS += ircomm
+O_OBJS += ircomm/ircomm_n_vtd.o
+else
+  ifeq ($(CONFIG_IRCOMM),m)
+  MOD_SUB_DIRS += ircomm
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+		tar -cvf /dev/f1 .
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.1.131/linux/net/irda/af_irda.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/af_irda.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,738 @@
+/*********************************************************************
+ *                
+ * Filename:      af_irda.c
+ * Version:       0.1
+ * Description:   IrDA sockets implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun May 31 10:12:43 1998
+ * Modified at:   Mon Dec 14 10:39:45 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       af_netroom.c, af_ax25.x
+ * 
+ *     Copyright (c) 1997 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/types.h>
+#include <linux/socket.h>
+#include <linux/sockios.h>
+#include <net/sock.h>
+#include <asm/segment.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irttp.h>
+
+extern int irda_init(void);
+extern void irda_cleanup(void);
+extern int irlap_input(struct sk_buff *, struct device *, struct packet_type *);
+
+#define IRDA_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
+
+#ifdef IRDA_SOCKETS
+
+/*
+ * Function irda_getname (sock, uaddr, uaddr_len, peer)
+ *
+ *    
+ *
+ */
+static int irda_getname( struct socket *sock, struct sockaddr *uaddr,
+			 int *uaddr_len, int peer)
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+
+	return 0;
+}
+
+/*
+ * 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)
+ *
+ *    
+ *
+ */
+static int irda_listen( struct socket *sock, int backlog)
+{
+#if 0
+	struct sock *sk = (struct sock *)sock->data;
+
+	if (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)
+ *
+ *    Connect to a IrDA device
+ *
+ */
+static int irda_connect( struct socket *sock, struct sockaddr *uaddr,
+	int addr_len, int flags)
+{
+#if 0
+	struct sock *sk = (struct sock *)sock->data;
+	struct sockaddr_irda *addr = (struct sockaddr_irda *)uaddr;
+	irda_address *user, *source = NULL;
+	struct device *dev;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
+		sock->state = SS_CONNECTED;
+		return 0;   /* Connect completed during a ERESTARTSYS event */
+	}
+	
+	if (sk->state == TCP_CLOSE && sock->state == SS_CONNECTING) {
+		sock->state = SS_UNCONNECTED;
+		return -ECONNREFUSED;
+	}
+	
+	if (sk->state == TCP_ESTABLISHED)
+		return -EISCONN;      /* No reconnect on a seqpacket socket */
+	
+	sk->state   = TCP_CLOSE;	
+	sock->state = SS_UNCONNECTED;
+
+	if (addr_len != sizeof(struct sockaddr_irda))
+		return -EINVAL;
+
+
+	/* Now the loop */
+	if (sk->state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
+		return -EINPROGRESS;
+		
+	cli();	/* To avoid races on the sleep */
+	
+	/* A Connect Ack with Choke or timeout or failed routing will go to
+	 * closed.  */
+	while ( sk->state == TCP_SYN_SENT) {
+		interruptible_sleep_on( sk->sleep);
+		if (current->signal & ~current->blocked) {
+			sti();
+			return -ERESTARTSYS;
+		}
+	}
+	
+	if (sk->state != TCP_ESTABLISHED) {
+		sti();
+		sock->state = SS_UNCONNECTED;
+		return sock_error( sk);	/* Always set at this point */
+	}
+	
+	sock->state = SS_CONNECTED;
+
+	sti();
+#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)
+ *
+ *    Create IrDA socket
+ *
+ */
+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;
+
+	/* Allocate socket */
+	if ((sk = sk_alloc( GFP_ATOMIC)) == NULL)
+		return -ENOMEM;
+
+	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;
+}
+
+/*
+ * Function irda_destroy_socket (tsap)
+ *
+ *    Destroy socket
+ *
+ */
+void irda_destroy_socket(struct tsap_cb *tsap)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	return;
+}
+
+/*
+ * Function irda_release (sock, peer)
+ *
+ *    
+ *
+ */
+static int irda_release( struct socket *sock, struct socket *peer)
+{
+#if 0
+        struct sock *sk = (struct sock *)sock->data;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+
+        if (sk == NULL) return 0;
+	
+        if (sk->type == SOCK_SEQPACKET) {                    
+
+	
+	} else {
+		sk->state       = TCP_CLOSE;
+                sk->shutdown   |= SEND_SHUTDOWN;
+                sk->state_change(sk);
+                sk->dead        = 1;
+                irda_destroy_socket( sk->protinfo.irda);
+        }
+
+        sock->data = NULL;      
+        sk->socket = NULL;      /* Not used, but we should do this. **/
+#endif
+        return 0;
+}
+
+
+/*
+ * Function irda_dup (newsock, oldsock)
+ *
+ *    
+ *
+ */
+static int irda_dup( struct socket *newsock, struct socket *oldsock)
+{
+#if 0
+        struct sock *sk = (struct sock *)oldsock->data;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+        if (sk == NULL || newsock == NULL)
+                return -EINVAL;
+
+        return irda_create( newsock, sk->protocol);
+#endif
+	return 0;
+}
+
+static int irda_shutdown( struct socket *sk, int how)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+        /* FIXME - generate DM and RNR states */
+        return -EOPNOTSUPP;
+}
+
+
+unsigned int irda_poll( struct file *file, struct socket *sock, 
+			struct poll_table_struct *wait)
+{
+	
+}
+
+/*
+ * Function irda_ioctl (sock, cmd, arg)
+ *
+ *    
+ *
+ */
+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)
+{
+#if 0
+        struct sock *sk = (struct sock *)sock->data;
+        int val = 0;
+        int err;
+
+	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);
+	
+        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");
+
+	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)
+{
+        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;
+}
+
+static struct proto_ops irda_proto_ops = {
+	AF_IRDA,
+	
+	irda_create,
+	irda_dup,
+	irda_release,
+	irda_bind,
+	irda_connect,
+	irda_socketpair,
+	irda_accept,
+	irda_getname,
+	irda_poll,
+	irda_ioctl,
+	irda_listen,
+	irda_shutdown,
+	irda_setsockopt,
+	irda_getsockopt,
+	irda_fcntl,
+	irda_sendmsg,
+	irda_recvmsg
+};
+
+#endif /* IRDA_SOCKETS */
+
+static int irda_device_event( struct notifier_block *this, unsigned long event,
+			      void *ptr)
+{
+	/* struct device *dev = (struct device *) ptr; */
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+        /* Reject non AX.25 devices */
+	/*  if (dev->type != ARPHRD_AX25) */
+/*                 return NOTIFY_DONE; */
+	
+        switch (event) {
+	case NETDEV_UP:
+		/* ax25_dev_device_up(dev); */
+		break;
+	case NETDEV_DOWN:
+		/* ax25_kill_by_device(dev); */
+/*                         ax25_rt_device_down(dev); */
+/*                         ax25_dev_device_down(dev); */
+		break;
+	default:
+		break;
+        }
+
+        return NOTIFY_DONE;
+}
+
+static struct packet_type irda_packet_type = 
+{
+	0,	/* MUTTER ntohs(ETH_P_IRDA),*/
+	NULL,
+	irlap_input, /* irda_driver_rcv, */
+	NULL,
+	NULL,
+};
+
+static struct notifier_block irda_dev_notifier = {
+	irda_device_event,
+	NULL,
+	0
+};
+
+/*
+ * Function irda_proto_init (pro)
+ *
+ *    Initialize IrDA protocol layer
+ *
+ */
+void irda_proto_init(struct net_proto *pro)
+{
+	DEBUG( 0, __FUNCTION__ "\n");
+
+	/* sock_register( irda_proto_ops.family, &irda_proto_ops); */
+	irda_packet_type.type = htons(ETH_P_IRDA);
+        dev_add_pack(&irda_packet_type);
+
+	/* register_netdevice_notifier( &irda_dev_notifier); */
+
+	/* printk( KERN_INFO "IrDA Sockets for Linux (Dag Brattli)\n"); */
+	irda_init();
+}
+
+/*
+ * Function irda_proto_cleanup (void)
+ *
+ *    Remove IrDA protocol layer
+ *
+ */
+void irda_proto_cleanup(void)
+{
+	DEBUG( 0, __FUNCTION__ "\n");
+
+	irda_packet_type.type = htons(ETH_P_IRDA);
+        dev_remove_pack(&irda_packet_type);
+
+        /* unregister_netdevice_notifier( &irda_dev_notifier); */
+	
+	/* (void) sock_unregister( irda_proto_ops.family); */
+	irda_cleanup();
+	
+        return;
+}
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/compressors/Config.in linux/net/irda/compressors/Config.in
--- v2.1.131/linux/net/irda/compressors/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/compressors/Config.in	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,9 @@
+
+bool 'IrLAP compression' CONFIG_IRDA_COMPRESSION
+
+if [ "$CONFIG_IRDA_COMPRESSION" != "n" ] ; then
+        comment '   IrDA compressors'
+        dep_tristate '   Deflate compression (experimental)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA
+#	tristate '   BZIP2 compression' CONFIG_IRDA_BZIP2
+#	tristate '   BSD compression' CONFIG_IRDA_BSD
+fi
diff -u --recursive --new-file v2.1.131/linux/net/irda/compressors/Makefile linux/net/irda/compressors/Makefile
--- v2.1.131/linux/net/irda/compressors/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/compressors/Makefile	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,26 @@
+#
+# Makefile for the Linux IRDA compression protocols
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET :=
+O_OBJS	 := 
+MOD_LIST_NAME := IRDA_MODULES
+M_OBJS   := 
+
+ifeq ($(CONFIG_IRDA_DEFLATE),y)
+O_OBJS += irda_deflate.o
+else
+  ifeq ($(CONFIG_IRDA_DEFLATE),m)
+  M_OBJS += irda_deflate.o
+  endif
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.1.131/linux/net/irda/compressors/irda_deflate.c linux/net/irda/compressors/irda_deflate.c
--- v2.1.131/linux/net/irda/compressors/irda_deflate.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/compressors/irda_deflate.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,635 @@
+/*********************************************************************
+ *                
+ * Filename:      irda_deflate.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Fri Oct  9 02:52:08 1998
+ * Modified at:   Mon Dec 14 19:48:54 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *  ==FILEVERSION 980319==
+ *
+ * irda_deflate.c - interface the zlib procedures for Deflate compression
+ * and decompression (as used by gzip) to the IrDA code.
+ * This version is for use with Linux kernel 2.1.X.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies.  This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h> 
+#include <linux/errno.h>
+#include <linux/sched.h>	/* to get the struct task_struct */
+#include <linux/string.h>	/* used in new tty drivers */
+#include <linux/signal.h>	/* used in new tty drivers */
+
+#include <asm/system.h>
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/ioctl.h>
+
+#include <linux/ppp_defs.h>
+#include <linux/ppp-comp.h>
+
+/*
+ * This is not that nice, but what can we do when the code has been placed
+ * elsewhere
+ */
+
+#include "../../../drivers/net/zlib.c"
+
+/*
+ * State for a Deflate (de)compressor.
+ */
+struct irda_deflate_state {
+    int		seqno;
+    int		w_size;
+    int		unit;
+    int		mru;
+    int		debug;
+    z_stream	strm;
+    struct compstat stats;
+};
+
+#define DEFLATE_OVHD	2		/* Deflate overhead/packet */
+
+static void	*zalloc __P((void *, unsigned int items, unsigned int size));
+static void	*zalloc_init __P((void *, unsigned int items,
+				  unsigned int size));
+static void	zfree __P((void *, void *ptr));
+static void	*z_comp_alloc __P((unsigned char *options, int opt_len));
+static void	*z_decomp_alloc __P((unsigned char *options, int opt_len));
+static void	z_comp_free __P((void *state));
+static void	z_decomp_free __P((void *state));
+static int	z_comp_init __P((void *state, unsigned char *options,
+				 int opt_len,
+				 int unit, int hdrlen, int debug));
+static int	z_decomp_init __P((void *state, unsigned char *options,
+				   int opt_len,
+				   int unit, int hdrlen, int mru, int debug));
+static int	z_compress __P((void *state, unsigned char *rptr,
+				unsigned char *obuf,
+				int isize, int osize));
+static void	z_incomp __P((void *state, unsigned char *ibuf, int icnt));
+static int	z_decompress __P((void *state, unsigned char *ibuf,
+				int isize, unsigned char *obuf, int osize));
+static void	z_comp_reset __P((void *state));
+static void	z_decomp_reset __P((void *state));
+static void	z_comp_stats __P((void *state, struct compstat *stats));
+
+struct chunk_header {
+	int valloced;		/* allocated with valloc, not kmalloc */
+	int guard;		/* check for overwritten header */
+};
+
+#define GUARD_MAGIC	0x77a8011a
+#define MIN_VMALLOC	2048	/* use kmalloc for blocks < this */
+
+/*
+ * Space allocation and freeing routines for use by zlib routines.
+ */
+void zfree(void *arg, void *ptr)
+{
+	struct chunk_header *hdr = ((struct chunk_header *)ptr) - 1;
+	
+	if (hdr->guard != GUARD_MAGIC) {
+		printk(KERN_WARNING "zfree: header corrupted (%x %x) at %p\n",
+		       hdr->valloced, hdr->guard, hdr);
+		return;
+	}
+	if (hdr->valloced)
+		vfree(hdr);
+	else
+		kfree(hdr);
+}
+
+void *
+zalloc(arg, items, size)
+    void *arg;
+    unsigned int items, size;
+{
+	struct chunk_header *hdr;
+	unsigned nbytes;
+
+	nbytes = items * size + sizeof(*hdr);
+	hdr = kmalloc(nbytes, GFP_ATOMIC);
+	if (hdr == 0)
+		return 0;
+	hdr->valloced = 0;
+	hdr->guard = GUARD_MAGIC;
+	return (void *) (hdr + 1);
+}
+
+void * zalloc_init(void *arg, unsigned int items, unsigned int size)
+{
+	struct chunk_header *hdr;
+	unsigned nbytes;
+
+	nbytes = items * size + sizeof(*hdr);
+	if (nbytes >= MIN_VMALLOC)
+		hdr = vmalloc(nbytes);
+	else
+		hdr = kmalloc(nbytes, GFP_KERNEL);
+	if (hdr == 0)
+		return 0;
+	hdr->valloced = nbytes >= MIN_VMALLOC;
+	hdr->guard = GUARD_MAGIC;
+	return (void *) (hdr + 1);
+}
+
+static void
+z_comp_free(arg)
+    void *arg;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	if (state) {
+		deflateEnd(&state->strm);
+		kfree(state);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+/*
+ * Allocate space for a compressor.
+ */
+static void *
+z_comp_alloc(options, opt_len)
+    unsigned char *options;
+    int opt_len;
+{
+	struct irda_deflate_state *state;
+	int w_size;
+
+	if (opt_len != CILEN_DEFLATE
+	    || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+	    || options[1] != CILEN_DEFLATE
+	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+	    || options[3] != DEFLATE_CHK_SEQUENCE)
+		return NULL;
+	w_size = DEFLATE_SIZE(options[2]);
+	w_size = MAX_WBITS;
+	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+		return NULL;
+
+	state = (struct irda_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	MOD_INC_USE_COUNT;
+	memset (state, 0, sizeof (struct irda_deflate_state));
+	state->strm.next_in = NULL;
+	state->strm.zalloc  = zalloc_init;
+	state->strm.zfree   = zfree;
+	state->w_size       = w_size;
+
+	if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION,
+			 DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY)
+	    != Z_OK)
+		goto out_free;
+	state->strm.zalloc = zalloc;
+	return (void *) state;
+
+out_free:
+	z_comp_free(state);
+	MOD_DEC_USE_COUNT;
+	return NULL;
+}
+
+static int
+z_comp_init(arg, options, opt_len, unit, hdrlen, debug)
+    void *arg;
+    unsigned char *options;
+    int opt_len, unit, hdrlen, debug;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	if (opt_len < CILEN_DEFLATE
+	    || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+	    || options[1] != CILEN_DEFLATE
+	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+	    || DEFLATE_SIZE(options[2]) != state->w_size
+	    || options[3] != DEFLATE_CHK_SEQUENCE)
+		return 0;
+
+	state->seqno = 0;
+	state->unit  = unit;
+	state->debug = debug;
+
+	deflateReset(&state->strm);
+
+	return 1;
+}
+
+static void z_comp_reset(void *arg)
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	state->seqno = 0;
+	deflateReset(&state->strm);
+}
+
+int
+z_compress(arg, rptr, obuf, isize, osize)
+    void *arg;
+    unsigned char *rptr;	/* uncompressed packet (in) */
+    unsigned char *obuf;	/* compressed packet (out) */
+    int isize, osize;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+	int r, olen, oavail;
+
+	olen = 0;
+
+	/* Don't generate compressed packets which are larger than
+	   the uncompressed packet. */
+	if (osize > isize)
+		osize = isize;
+
+	state->strm.next_out = obuf;
+	state->strm.avail_out = oavail = osize;
+
+	state->strm.next_in = rptr;
+	state->strm.avail_in = isize;
+
+	for (;;) {
+		r = deflate(&state->strm, Z_PACKET_FLUSH);
+		if (r != Z_OK) {
+			if (state->debug)
+				printk(KERN_ERR
+				       "z_compress: deflate returned %d\n", r);
+			break;
+		}
+		if (state->strm.avail_out == 0) {
+			olen += oavail;
+			state->strm.next_out = NULL;
+			state->strm.avail_out = oavail = 1000000;
+		} else {
+			break;		/* all done */
+		}
+	}
+	olen += oavail - state->strm.avail_out;
+
+	/*
+	 * See if we managed to reduce the size of the packet.
+	 */
+	if (olen < isize) {
+		state->stats.comp_bytes += olen;
+		state->stats.comp_packets++;
+	} else {
+		state->stats.inc_bytes += isize;
+		state->stats.inc_packets++;
+		olen = 0;
+	}
+	state->stats.unc_bytes += isize;
+	state->stats.unc_packets++;
+
+	return olen;
+}
+
+static void
+z_comp_stats(arg, stats)
+    void *arg;
+    struct compstat *stats;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	*stats = state->stats;
+}
+
+static void z_decomp_free(void *arg)
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	if (state) {
+		inflateEnd(&state->strm);
+		kfree(state);
+		MOD_DEC_USE_COUNT;
+	}
+}
+
+/*
+ * Allocate space for a decompressor.
+ */
+static void *
+z_decomp_alloc(options, opt_len)
+    unsigned char *options;
+    int opt_len;
+{
+	struct irda_deflate_state *state;
+	int w_size;
+
+	if (opt_len != CILEN_DEFLATE
+	    || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+	    || options[1] != CILEN_DEFLATE
+	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+	    || options[3] != DEFLATE_CHK_SEQUENCE)
+		return NULL;
+	w_size = DEFLATE_SIZE(options[2]);
+	w_size = MAX_WBITS;
+	if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE)
+		return NULL;
+
+	state = (struct irda_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL);
+	if (state == NULL)
+		return NULL;
+
+	MOD_INC_USE_COUNT;
+	memset (state, 0, sizeof (struct irda_deflate_state));
+	state->w_size        = w_size;
+	state->strm.next_out = NULL;
+	state->strm.zalloc   = zalloc_init;
+	state->strm.zfree    = zfree;
+
+	if (inflateInit2(&state->strm, -w_size) != Z_OK)
+		goto out_free;
+	state->strm.zalloc = zalloc;
+	return (void *) state;
+
+out_free:
+	z_decomp_free(state);
+	MOD_DEC_USE_COUNT;
+	return NULL;
+}
+
+static int
+z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug)
+    void *arg;
+    unsigned char *options;
+    int opt_len, unit, hdrlen, mru, debug;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	if (opt_len < CILEN_DEFLATE
+	    || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT)
+	    || options[1] != CILEN_DEFLATE
+	    || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL
+	    || DEFLATE_SIZE(options[2]) != state->w_size
+	    || options[3] != DEFLATE_CHK_SEQUENCE)
+		return 0;
+
+	state->seqno = 0;
+	state->unit  = unit;
+	state->debug = debug;
+	state->mru   = mru;
+
+	inflateReset(&state->strm);
+
+	return 1;
+}
+
+static void z_decomp_reset(void *arg)
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+
+	state->seqno = 0;
+	inflateReset(&state->strm);
+}
+
+/*
+ * Decompress a Deflate-compressed packet.
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression.  For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+int
+z_decompress(arg, ibuf, isize, obuf, osize)
+    void *arg;
+    unsigned char *ibuf;
+    int isize;
+    unsigned char *obuf;
+    int osize;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+	int olen, r;
+	int overflow;
+	unsigned char overflow_buf[1];
+
+	if (isize <= DEFLATE_OVHD) {
+		if (state->debug)
+			printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n",
+			       state->unit, isize);
+		return DECOMP_ERROR;
+	}
+
+	/*
+	 * Set up to call inflate.
+	 */
+	state->strm.next_in = ibuf;
+	state->strm.avail_in = isize;
+	state->strm.next_out = obuf;
+	state->strm.avail_out = osize;
+	overflow = 0;
+
+	/*
+	 * Call inflate, supplying more input or output as needed.
+	 */
+	for (;;) {
+		r = inflate(&state->strm, Z_PACKET_FLUSH);
+		if (r != Z_OK) {
+			if (state->debug)
+				printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n",
+				       state->unit, r, (state->strm.msg? state->strm.msg: ""));
+			return DECOMP_FATALERROR;
+		}
+		if (state->strm.avail_out != 0)
+			break;		/* all done */
+		
+		if (!overflow) {
+			/*
+			 * We've filled up the output buffer; the only way to
+			 * find out whether inflate has any more characters
+			 * left is to give it another byte of output space.
+			 */
+			state->strm.next_out = overflow_buf;
+			state->strm.avail_out = 1;
+			overflow = 1;
+		} else {
+			if (state->debug)
+				printk(KERN_DEBUG "z_decompress%d: ran out of mru\n",
+				       state->unit);
+			return DECOMP_FATALERROR;
+		}
+	}
+
+	olen = osize + overflow - state->strm.avail_out;
+	state->stats.unc_bytes += olen;
+	state->stats.unc_packets++;
+	state->stats.comp_bytes += isize;
+	state->stats.comp_packets++;
+
+	return olen;
+}
+
+/*
+ * Incompressible data has arrived - add it to the history.
+ */
+static void
+z_incomp(arg, ibuf, icnt)
+    void *arg;
+    unsigned char *ibuf;
+    int icnt;
+{
+	struct irda_deflate_state *state = (struct irda_deflate_state *) arg;
+	int r;
+
+	/*
+	 * Check that the protocol is one we handle.
+	 */
+
+	/*
+	 * We start at the either the 1st or 2nd byte of the protocol field,
+	 * depending on whether the protocol value is compressible.
+	 */
+	state->strm.next_in = ibuf;
+	state->strm.avail_in = icnt;
+
+	r = inflateIncomp(&state->strm);
+	if (r != Z_OK) {
+		/* gak! */
+		if (state->debug) {
+			printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n",
+			       state->unit, r, (state->strm.msg? state->strm.msg: ""));
+		}
+		return;
+	}
+
+	/*
+	 * Update stats.
+	 */
+	state->stats.inc_bytes += icnt;
+	state->stats.inc_packets++;
+	state->stats.unc_bytes += icnt;
+	state->stats.unc_packets++;
+}
+
+/*************************************************************
+ * Module interface table
+ *************************************************************/
+
+/* These are in ppp.c */
+extern int  irda_register_compressor   (struct compressor *cp);
+extern void irda_unregister_compressor (struct compressor *cp);
+
+/*
+ * Procedures exported to if_ppp.c.
+ */
+static struct compressor irda_deflate = {
+	CI_DEFLATE,		/* compress_proto */
+	z_comp_alloc,		/* comp_alloc */
+	z_comp_free,		/* comp_free */
+	z_comp_init,		/* comp_init */
+	z_comp_reset,		/* comp_reset */
+	z_compress,		/* compress */
+	z_comp_stats,		/* comp_stat */
+	z_decomp_alloc,		/* decomp_alloc */
+	z_decomp_free,		/* decomp_free */
+	z_decomp_init,		/* decomp_init */
+	z_decomp_reset,		/* decomp_reset */
+	z_decompress,		/* decompress */
+	z_incomp,		/* incomp */
+	z_comp_stats,		/* decomp_stat */
+};
+
+static struct compressor irda_deflate_draft = {
+	CI_DEFLATE_DRAFT,	/* compress_proto */
+	z_comp_alloc,		/* comp_alloc */
+	z_comp_free,		/* comp_free */
+	z_comp_init,		/* comp_init */
+	z_comp_reset,		/* comp_reset */
+	z_compress,		/* compress */
+	z_comp_stats,		/* comp_stat */
+	z_decomp_alloc,		/* decomp_alloc */
+	z_decomp_free,		/* decomp_free */
+	z_decomp_init,		/* decomp_init */
+	z_decomp_reset,		/* decomp_reset */
+	z_decompress,		/* decompress */
+	z_incomp,		/* incomp */
+	z_comp_stats,		/* decomp_stat */
+};
+
+__initfunc(int irda_deflate_init(void))
+{
+        int answer = irda_register_compressor ( &irda_deflate);
+        if (answer == 0)
+                printk (KERN_INFO
+			"IrDA Deflate Compression module registered\n");
+	irda_register_compressor( &irda_deflate_draft);
+        return answer;
+}
+
+void irda_deflate_cleanup(void)
+{
+
+	irda_unregister_compressor (&irda_deflate);
+	irda_unregister_compressor (&irda_deflate_draft);
+}
+
+#ifdef MODULE
+/*************************************************************
+ * Module support routines
+ *************************************************************/
+
+int init_module(void)
+{  
+	return irda_deflate_init();
+}
+     
+void
+cleanup_module(void)
+{
+	if (MOD_IN_USE)
+		printk (KERN_INFO
+			"Deflate Compression module busy, remove delayed\n");
+	else {
+		irda_deflate_cleanup();
+	}
+}
+#endif
diff -u --recursive --new-file v2.1.131/linux/net/irda/crc.c linux/net/irda/crc.c
--- v2.1.131/linux/net/irda/crc.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/crc.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,65 @@
+/*********************************************************************
+ *                
+ * Filename:      crc.c
+ * Version:       0.1
+ * Description:   CRC calculation routines
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Aug  4 20:40:53 1997
+ * Modified at:   Sat Dec 12 09:56:35 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       ppp.c by Michael Callahan <callahan@maths.ox.ac.uk>
+ *                Al Longyear <longyear@netcom.com>
+ *
+ ********************************************************************/
+
+#include <net/irda/crc.h>
+
+/*
+ * This mysterious table is just the CRC of each possible byte.  It can be
+ * computed using the standard bit-at-a-time methods.  The polynomial can
+ * be seen in entry 128, 0x8408.  This corresponds to x^0 + x^5 + x^12.
+ * Add the implicit x^16, and you have the standard CRC-CCITT.
+ */
+__u16 const irda_crc16_table[256] =
+{
+	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len) 
+{
+    while ( len--)
+		fcs = IR_FCS(fcs, *buf++);
+    return fcs;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/ircomm/Config.in linux/net/irda/ircomm/Config.in
--- v2.1.131/linux/net/irda/ircomm/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/Config.in	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,3 @@
+
+dep_tristate 'IrCOMM protocol' CONFIG_IRCOMM $CONFIG_IRDA
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/ircomm/Makefile linux/net/irda/ircomm/Makefile
--- v2.1.131/linux/net/irda/ircomm/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/Makefile	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,31 @@
+#
+# Makefile for the Linux IrDA IrCOMM protocol layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+O_TARGET := ircomm_n_vtd.o
+O_OBJS	 := ircomm_common.o attach.o irvtd.o irvtd_driver.o
+M_OBJS   := ircomm.o ircomm_tty.o
+MI_OBJS  := ircomm_common.o attach.o irvtd.o irvtd_driver.o
+
+OX_OBJS  += 
+
+# Special rule to build the composite modules
+
+ifeq ($(CONFIG_IRCOMM),m)
+ircomm.o:  $(MI_OBJS)
+	$(LD) $(LD_RFLAG) -r -o $@ ircomm_common.o attach.o
+
+ircomm_tty.o: $(MI_OBJS)
+	$(LD) $(LD_RFLAG) -r -o $@ irvtd.o irvtd_driver.o
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+		tar -cvf /dev/f1 .
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/ircomm/attach.c linux/net/irda/ircomm/attach.c
--- v2.1.131/linux/net/irda/ircomm/attach.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/attach.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,364 @@
+/*********************************************************************
+ *                
+ * Filename:      attach.c
+ * Version:       
+ * Description:   An implementation of IrCOMM service interface.
+ * Status:        Experimental.
+ * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
+ *
+ *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+
+/*
+ * ----------------------------------------------------------------------
+ * IrIAS related things for IrCOMM
+ * If you are to use ircomm layer, use ircomm_attach_cable to
+ * setup it and register your program.
+ * ----------------------------------------------------------------------
+ */
+
+
+#include <linux/sched.h>
+#include <linux/tqueue.h>
+
+#include <net/irda/irlap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irias_object.h>
+
+#include <net/irda/ircomm_common.h>
+
+extern struct ircomm_cb **ircomm;
+struct ircomm_cb *discovering_instance;
+
+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 );
+
+#if 0
+static char *rcsid = "$Id: attach.c,v 1.11 1998/10/22 12:02:20 dagb Exp $";
+#endif
+
+
+/*
+ * handler for iriap_getvaluebyclass_request() 
+ *
+ */
+
+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;);
+
+	DEBUG(0, __FUNCTION__"type(%d)\n", value->type);
+
+	switch(value->type){
+
+ 	case IAS_OCT_SEQ:
+ 		/* 
+		 * FIXME:we should use data which came here
+		 * it is used for nothing at this time 
+		 */
+		
+#if 1
+		DEBUG(0, "octet sequence is:\n");
+		{
+			int i;
+			for ( i=0;i<value->len;i++)
+				printk("%02x",
+				       (int)(*value->t.oct_seq + i) );
+			printk("\n");
+		}
+#endif
+		query_lsapsel(self);
+		break;
+
+	case IAS_INTEGER:
+		/* LsapSel seems to be sent to me */	
+
+		if ( value->t.integer == -1){
+			DEBUG( 0, "ircomm_getvalue_confirm: invalid value!\n");
+			return;
+		}
+		if(self->state == COMM_IDLE){
+			self->dlsap = value->t.integer;
+			got_lsapsel(self);
+		}
+		break;
+
+	case IAS_STRING:
+		DEBUG( 0, __FUNCTION__":STRING is not implemented\n");
+		DEBUG( 0, __FUNCTION__":received string:%s\n",
+		       value->t.string);
+		query_lsapsel(self);  /* experiment */
+		break;
+
+	case IAS_MISSING:
+		DEBUG( 0, __FUNCTION__":MISSING is not implemented\n");
+		break;
+   
+	default:
+		DEBUG( 0, __FUNCTION__":unknown type!\n");
+		break;
+	}
+}
+
+
+static void got_lsapsel(struct ircomm_cb * self){
+
+	struct notify_t notify;
+
+	DEBUG(0, "ircomm:got_lsapsel: got peersap!(%d)\n", self->dlsap );
+
+	/* remove tsap for server */
+	irttp_close_tsap(self->tsap);
+
+	/* create TSAP for initiater ... */
+	irda_notify_init(&notify);
+	notify.data_indication = ircomm_accept_data_indication;
+	notify.connect_confirm = ircomm_accept_connect_confirm;
+	notify.connect_indication = ircomm_accept_connect_indication;
+	notify.flow_indication = ircomm_accept_flow_indication;
+	notify.disconnect_indication = ircomm_accept_disconnect_indication;
+	strncpy( notify.name, "IrCOMM cli", NOTIFY_MAX_NAME);
+	notify.instance = self;
+	
+	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
+	 */
+
+	ircomm_next_state(self, COMM_IDLE);	
+  	if(self->d_handler)
+ 		self->d_handler(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 );
+	} else {
+		DEBUG(0,"ircomm:query_lsap:"
+		      "THREE_WIRE_RAW is not implemented!\n");
+	}
+}
+
+
+
+/*
+ * ircomm_discovery_indication()
+ *    Remote device is discovered, try query the remote IAS to see which
+ *    device it is, and which services it has.
+ */
+
+void ircomm_discovery_indication( DISCOVERY *discovery)
+{
+
+	struct ircomm_cb *self;
+
+ 	DEBUG( 0, "ircomm_discovery_indication\n");
+	
+	self = discovering_instance;
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_MAGIC, return;);
+
+	self->daddr = discovery->daddr;
+
+	DEBUG( 0, "ircomm_discovery_indication:daddr=%08x\n", self->daddr);
+
+	/* query "Parameters" attribute of LM-IAS */
+
+	DEBUG(0, "ircomm:querying parameters..\n");
+#if 0
+	iriap_getvaluebyclass_request(self->daddr, "IrDA:IrCOMM",
+
+				      "Parameters",
+				      ircomm_getvalue_confirm,
+				      self);
+#else
+	query_lsapsel(self);
+#endif
+	return;
+}
+
+
+struct ircomm_cb * ircomm_attach_cable( __u8 servicetype,
+					struct notify_t notify, 
+					void *handler ){
+
+	int i;
+	struct ircomm_cb *self = NULL;
+	struct notify_t server_notify;
+	struct ias_object* obj;
+
+	/* FIXME: it should not be hard coded */
+	__u8 oct_seq[6] = { 0,1,4,1,1,1 }; 
+
+	ASSERT(ircomm != NULL,return NULL;);
+	DEBUG(0,"ircomm_attach_cable:\n");
+
+
+	/* find free handle */
+
+	for(i = 0; i < IRCOMM_MAX_CONNECTION; i++){
+		ASSERT(ircomm[i] != NULL,return(NULL););
+		if(!ircomm[i]->in_use){
+			self = ircomm[i];
+			break;
+		}
+	}
+
+	if (!self){
+		DEBUG(0,"ircomm_attach_cable:no free handle!\n");
+		return (NULL);
+	}
+
+	self->in_use = 1;
+	self->servicetype = servicetype;
+
+	DEBUG(0,"attach_cable:servicetype:%d\n",servicetype);
+	self->d_handler = handler;
+	self->notify = notify;
+
+	/* register server.. */
+
+	/*
+	 * TODO: since server TSAP is currentry hard coded,
+	 * we can use *only one* IrCOMM connection.
+	 * We have to create one more TSAP and register IAS entry dynamically 
+	 * each time when we are to allocate new server here.
+	 */
+	irda_notify_init(&server_notify);
+	server_notify.data_indication = ircomm_accept_data_indication;
+	server_notify.connect_confirm = ircomm_accept_connect_confirm;
+	server_notify.connect_indication = ircomm_accept_connect_indication;
+	server_notify.flow_indication = ircomm_accept_flow_indication;
+	server_notify.disconnect_indication = ircomm_accept_disconnect_indication;
+	server_notify.instance = self;
+	strncpy( server_notify.name, "IrCOMM srv", NOTIFY_MAX_NAME);
+
+	self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT,
+				     &server_notify);
+	if(!self->tsap){
+		DEBUG(0,"ircomm:Sorry, failed to allocate server_tsap\n");
+		return NULL;
+	}
+
+        /* 
+         *  Register with LM-IAS
+         */
+	obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID);
+	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", 
+				  self->tsap->stsap_sel );
+
+	/* FIXME: it should not be hard coded */
+
+	irias_add_octseq_attrib( obj, "Parameters", 
+				 &oct_seq[0], 6);
+	irias_insert_object( obj);
+
+/* 	obj = irias_new_object( "IrDA:IrCOMM", IAS_IRCOMM_ID); */
+/* 	irias_add_octseq_attrib( obj, "Parameters", len, &octseq); */
+/* 	irias_insert_object( obj); */
+
+
+
+	/* and start discovering .. */
+	discovering_instance = self;
+
+	switch(servicetype){
+	case NINE_WIRE:
+		DEBUG(0,"ircomm_attach_cable:discovering..\n");
+		irlmp_register_layer(S_COMM , CLIENT|SERVER, TRUE,
+				     ircomm_discovery_indication);
+		break;
+
+/* 	case CENTRONICS: */
+/* 	case THREE_WIRE: */
+/* 	case THREE_WIRE_RAW: */
+
+	default:
+		DEBUG(0,"ircomm_attach_cable:requested servicetype is not "
+		      "implemented!\n");
+		return NULL;
+	}
+
+	ircomm_next_state(self, COMM_IDLE);	
+	return (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 */
+	if(self->state != COMM_IDLE ){
+		DEBUG(0,"ircomm:detach_cable:not IDLE\n");
+		if(self->state != COMM_WAITI)
+			ircomm_disconnect_request(self, NULL);
+	}
+
+
+	switch(self->servicetype){
+/* 	case CENTRONICS: */
+	case NINE_WIRE:
+/* 	case THREE_WIRE: */
+		irlmp_unregister_layer( S_COMM, CLIENT|SERVER );
+		break;
+
+/* 	case THREE_WIRE_RAW: */
+/* 		irlmp_unregister( S_COMM ) */
+/*		irlmp_unregister( S_PRINTER) */
+/* 		break; */
+
+	default:
+		DEBUG(0,"ircomm_detach_cable:requested servicetype is not "
+		      "implemented!\n");
+		return -ENODEV;
+	}
+
+	/* remove tsaps */
+	if(self->tsap)
+		irttp_close_tsap(self->tsap);
+
+	self->tsap = NULL;
+	self->in_use = 0;
+	return 0;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/ircomm/ircomm_common.c linux/net/irda/ircomm/ircomm_common.c
--- v2.1.131/linux/net/irda/ircomm/ircomm_common.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/ircomm_common.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1290 @@
+/*********************************************************************
+ *                
+ * Filename:      ircomm_common.c
+ * Version:       
+ * Description:   An implementation of IrCOMM service interface, 
+ *                state machine, and incidental function(s).
+ * Status:        Experimental.
+ * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
+ * Source:        irlpt_event.c
+ *
+ *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+/*
+ *    Reference: 
+ *    "'IrCOMM':Serial and Parallel Port Emulation Over IR(Wire Replacement)"
+ *    version 1.0, which is available at http://www.irda.org/.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irmod.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/ircomm_common.h>
+
+#if 0
+static char *rcsid = "$Id: ircomm_common.c,v 1.13 1998/10/13 12:59:05 takahide Exp $";
+#endif
+static char *version = "IrCOMM_common, $Revision: 1.13 $ $Date: 1998/10/13 12:59:05 $ (Takahide Higuchi)";
+
+
+
+
+static void ircomm_state_discovery( struct ircomm_cb *self,
+				  IRCOMM_EVENT event, struct sk_buff *skb );
+static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
+			       struct sk_buff *skb );
+static void ircomm_state_waiti( struct ircomm_cb *self, IRCOMM_EVENT event, 
+				struct sk_buff *skb );
+static void ircomm_state_waitr( struct ircomm_cb *self, IRCOMM_EVENT event, 
+				struct sk_buff *skb );
+static void ircomm_state_conn( struct ircomm_cb *self, IRCOMM_EVENT event, 
+			       struct sk_buff *skb );
+static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
+			     struct sk_buff *skb);
+void ircomm_next_state( struct ircomm_cb *self, IRCOMM_STATE state);
+
+int ircomm_check_handle(int handle);
+
+static void ircomm_parse_control(struct ircomm_cb *self, struct sk_buff *skb,
+				 int type);
+static char *ircommstate[] = {
+	"DISCOVERY",
+	"IDLE",
+	"WAITI",
+	"WAITR",
+	"CONN",
+};
+
+static char *ircommservicetype[] = {
+	"N/A",
+	"THREE_WIRE_RAW",
+	"THREE_WIRE",
+	"NINE_WIRE",
+	"CENTRONICS",
+};
+static char *ircommporttype[] = {
+	"Unknown",
+	"SERIAL",
+	"PARALLEL",
+};
+
+
+struct ircomm_cb **ircomm = NULL;
+
+static char *ircommevent[] = {
+	"IRCOMM_CONNECT_REQUEST",
+	"TTP_CONNECT_INDICATION",
+	"LMP_CONNECT_INDICATION",
+
+	"TTP_CONNECT_CONFIRM",
+	"TTP_DISCONNECT_INDICATION",
+	"LMP_CONNECT_CONFIRM",
+	"LMP_DISCONNECT_INDICATION",
+
+	"IRCOMM_CONNECT_RESPONSE",
+	"IRCOMM_DISCONNECT_REQUEST",
+
+	"TTP_DATA_INDICATION",
+	"IRCOMM_DATA_REQUEST",
+	"LMP_DATA_INDICATION",
+	"IRCOMM_CONTROL_REQUEST",
+};
+
+int ircomm_proc_read(char *buf, char **start, off_t offset,
+		     int len, int unused);
+
+#ifdef CONFIG_PROC_FS
+extern struct proc_dir_entry proc_irda;
+struct proc_dir_entry proc_ircomm = {
+	0, 6, "ircomm",
+        S_IFREG | S_IRUGO, 1, 0, 0,
+        0, NULL,
+        &ircomm_proc_read,
+};
+#endif
+
+static void (*state[])( struct ircomm_cb *self, IRCOMM_EVENT event,
+			struct sk_buff *skb) = 
+{
+	ircomm_state_discovery,
+	ircomm_state_idle,
+	ircomm_state_waiti,
+	ircomm_state_waitr,
+	ircomm_state_conn,
+};
+
+
+__initfunc(int ircomm_init(void))
+{
+	int i;
+
+	printk( KERN_INFO "%s\n", version);
+	DEBUG( 4, "ircomm_common:init_module\n");
+
+	/* allocate master array */
+
+	ircomm = (struct ircomm_cb **) kmalloc( sizeof(struct ircomm_cb *) *
+						IRCOMM_MAX_CONNECTION,
+						GFP_KERNEL);
+	if ( ircomm == NULL) {
+		printk( KERN_WARNING "IrCOMM: Can't allocate ircomm array!\n");
+		return -ENOMEM;
+	}
+
+	memset( ircomm, 0, sizeof(struct ircomm_cb *) * IRCOMM_MAX_CONNECTION);
+
+	/* initialize structures */
+	   
+	for(i = 0;i < IRCOMM_MAX_CONNECTION; i++){
+		ircomm[i] = kmalloc( sizeof(struct ircomm_cb), GFP_KERNEL );
+
+		if(!ircomm[i]){
+			printk(KERN_ERR "ircomm:kmalloc failed!\n");
+			return -ENOMEM;
+		} 
+
+		
+		memset( ircomm[i], 0, sizeof(struct ircomm_cb));
+
+		ircomm[i]->magic = IRCOMM_MAGIC;
+		/* default settings */
+		ircomm[i]->data_format = CS8;
+		ircomm[i]->flow_ctrl = USE_RTS|USE_DTR;  /*TODO: is this OK? */
+		ircomm[i]->xon_char = 0x11; 
+		ircomm[i]->xoff_char = 0x13;
+		ircomm[i]->enq_char = 0x05;
+		ircomm[i]->ack_char = 0x06;  
+
+		ircomm[i]->max_txbuff_size = COMM_DEFAULT_DATA_SIZE;   /* 64 */
+		ircomm[i]->maxsdusize = SAR_DISABLE;  
+		ircomm[i]->ctrl_skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+		if (ircomm[i]->ctrl_skb == NULL){
+			DEBUG(0,"ircomm:init_module:alloc_skb failed!\n");
+			return -ENOMEM;
+		}
+
+		skb_reserve(ircomm[i]->ctrl_skb,COMM_HEADER_SIZE);
+
+	}
+
+	/*
+	 * we register /proc/irda/ircomm
+	 */
+
+#ifdef CONFIG_PROC_FS
+	proc_register( &proc_irda, &proc_ircomm);
+#endif /* CONFIG_PROC_FS */
+
+	return 0;
+}
+
+void ircomm_cleanup(void)
+{
+	int i;
+
+	DEBUG( 4, "ircomm_common:cleanup_module\n");
+	/*
+	 * free some resources
+	 */
+	if (ircomm) {
+		for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
+			if (ircomm[i]) {
+
+				if(ircomm[i]->ctrl_skb){
+					dev_kfree_skb(ircomm[i]->ctrl_skb);
+
+					ircomm[i]->ctrl_skb = NULL;
+				}
+
+				DEBUG( 4, "freeing structures(%d)\n",i);
+				kfree(ircomm[i]);
+				ircomm[i] = NULL;
+			}
+		}
+		DEBUG( 4, "freeing master array\n");
+		kfree(ircomm);
+		ircomm = NULL;
+	}
+
+#ifdef CONFIG_PROC_FS
+	proc_unregister( &proc_irda, proc_ircomm.low_ino);
+#endif
+}
+
+/*
+ * ---------------------------------------------------------------------- 
+ * callbacks which accept incoming indication/confirm from IrTTP  (or IrLMP)
+ * ---------------------------------------------------------------------- 
+ */
+
+void ircomm_accept_data_indication(void *instance, void *sap, struct sk_buff *skb){
+	
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+       
+	DEBUG(4,"ircomm_accept_data_indication:\n");
+	ircomm_do_event( self, TTP_DATA_INDICATION, skb);
+}
+
+void ircomm_accept_connect_confirm(void *instance, void *sap,
+				   struct qos_info *qos, 
+				   int maxsdusize, struct sk_buff *skb){
+
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( qos != NULL, return;);
+
+	DEBUG(0,"ircomm_accept_connect_confirm:\n");
+
+	if(maxsdusize == SAR_DISABLE)
+		self->max_txbuff_size = qos->data_size.value; 
+	else {
+		ASSERT(maxsdusize >= COMM_DEFAULT_DATA_SIZE, return;);
+		self->max_txbuff_size = maxsdusize; /* use fragmentation */
+	}
+
+	self->qos = qos;
+	self->null_modem_mode = 0;            	/* disable null modem emulation */
+
+	ircomm_do_event( self, TTP_CONNECT_CONFIRM, skb);
+}
+
+void ircomm_accept_connect_indication(void *instance, void *sap,
+				      struct qos_info *qos,
+				      int maxsdusize,
+				      struct sk_buff *skb ){
+
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( qos != NULL, return;);
+
+	DEBUG(0,"ircomm_accept_connect_indication:\n");
+
+	if(maxsdusize == SAR_DISABLE)
+		self->max_txbuff_size = qos->data_size.value;
+	else
+		self->max_txbuff_size = maxsdusize;
+
+	self->qos = qos;
+	ircomm_do_event( self, TTP_CONNECT_INDICATION, 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;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	DEBUG(0,"ircomm_accept_disconnect_indication:\n");
+	ircomm_do_event( self, TTP_DISCONNECT_INDICATION, skb);
+}
+
+void ircomm_accept_flow_indication( void *instance, void *sap, LOCAL_FLOW cmd){
+	
+	struct ircomm_cb *self = (struct ircomm_cb *)instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+
+	switch(cmd){
+	case FLOW_START:
+		DEBUG(0,"ircomm_accept_flow_indication:START\n"); 
+
+		self->pi = TX_READY;
+		self->ttp_stop = 0;
+		if(self->notify.flow_indication)
+			self->notify.flow_indication( self->notify.instance, 
+						      self, cmd);
+		ircomm_control_request(self);
+		break;
+		
+	case FLOW_STOP:
+		DEBUG(0,"ircomm_accept_flow_indication:STOP\n"); 
+		self->pi = TX_BUSY;
+		self->ttp_stop = 1;
+		if(self->notify.flow_indication)
+			self->notify.flow_indication( self->notify.instance, 
+						      self, cmd);
+		break;
+
+	default:
+		DEBUG(0,"ircomm_accept_flow_indication:unknown status!\n"); 
+	}
+
+}
+
+/* 
+ * ----------------------------------------------------------------------
+ * Implementation of actions,descrived in section 7.4 of the reference.
+ * ----------------------------------------------------------------------
+ */
+
+
+static void issue_connect_request(struct ircomm_cb *self,
+				  struct sk_buff *userdata ){
+
+	/* TODO: we have to send/build userdata field which contains 
+	   InitialControlParameters */
+	/* but userdata field is not implemeted in irttp.c.. */
+
+	switch(self->servicetype){
+	case THREE_WIRE_RAW:
+		/* not implemented yet! Do nothing */
+		DEBUG(0, "ircomm:issue_connect_request:"
+		      "not implemented servicetype!");
+		break;
+
+	case DEFAULT: 
+		irttp_connect_request(self->tsap, self->dlsap, self->daddr,
+				      NULL, self->maxsdusize, NULL);  
+ 		break; 
+		
+	case THREE_WIRE:
+	case NINE_WIRE:
+	case CENTRONICS:
+
+		irttp_connect_request(self->tsap, self->dlsap, self->daddr, 
+				      NULL, self->maxsdusize, NULL); 
+		break;
+
+	default:
+		DEBUG(0,"ircomm:issue_connect_request:Illegal servicetype %d\n"
+		      ,self->servicetype);
+	}
+}	
+
+
+static void disconnect_indication(struct ircomm_cb *self, struct sk_buff *skb){
+
+	/*
+	 * Not implemented parameter"Reason".That is optional.
+	 * What is reason? maybe discribed in irmod.h?
+	 */
+
+	if(self->notify.disconnect_indication)
+		self->notify.disconnect_indication( self->notify.instance,
+						    self,
+						    self->reason,skb);
+						    
+}
+
+static void connect_indication(struct ircomm_cb *self, struct qos_info *qos, 
+			       struct sk_buff *skb){
+
+/* If controlparameters don't exist, we use the servicetype"DEFAULT".*/
+/* 	if( !ircomm_parse_controlchannel( self, data)) */
+/* 		self->servicetype = DEFAULT;     TODOD:fix this! TH */
+
+	if(self->notify.connect_indication)
+		self->notify.connect_indication(self->notify.instance, self, 
+						qos, 0, skb);
+}
+    
+#if 0
+/*   it's for THREE_WIRE_RAW.*/
+static void connect_indication_three_wire_raw(void){ 
+	DEBUG(0,"ircomm:connect_indication_threewire():not implemented!");
+}    
+#endif 
+
+
+static void connect_confirmation(struct ircomm_cb *self, struct sk_buff *skb){
+
+	/* give a connect_confirm to the client */
+	if( self->notify.connect_confirm )
+		self->notify.connect_confirm(self->notify.instance,
+					     self, NULL, SAR_DISABLE, skb);
+}
+
+static void issue_connect_response(struct ircomm_cb *self,
+				   struct sk_buff *skb ){
+
+	DEBUG(0,"ircomm:issue_connect_response:\n");
+	
+	if( self->servicetype == THREE_WIRE_RAW){
+		DEBUG(0,"ircomm:issue_connect_response():3WIRE-RAW is not " 
+		      "implemented yet !\n");
+		/* irlmp_connect_rsp(); */
+	} else {
+		irttp_connect_response(self->tsap, self->maxsdusize, skb);
+	}
+}
+
+static void issue_disconnect_request(struct ircomm_cb *self,
+				struct sk_buff *userdata ){
+	if(self->servicetype == THREE_WIRE_RAW){
+		DEBUG(0,"ircomm:issue_disconnect_request():3wireraw is not implemented!");
+	}
+	else
+		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
+}
+    
+static void issue_data_request(struct ircomm_cb *self,
+			       struct sk_buff *userdata ){
+	int err;
+
+	if(self->servicetype == THREE_WIRE_RAW){
+		/* irlmp_data_request(self->lmhandle,userdata); */
+		DEBUG(0,"ircomm:issue_data_request():not implemented!");
+		return;
+	}
+
+	DEBUG(4,"ircomm:issue_data_request():sending frame\n");
+	err = irttp_data_request(self->tsap , userdata  );
+	if(err)
+		DEBUG(0,"ircomm:ttp_data_request failed\n");
+	if(userdata && err)
+		dev_kfree_skb( userdata);
+
+}
+
+static void issue_control_request(struct ircomm_cb *self,
+				  struct sk_buff *userdata ){
+	if(self->servicetype == THREE_WIRE_RAW){
+		DEBUG(0,"THREE_WIRE_RAW is not implemented\n");
+		
+	}else {
+		irttp_data_request(self->tsap,userdata);
+	}
+}
+
+
+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]);
+
+	/* 
+	 * we always have to parse control channel
+	 *  (see page17 of IrCOMM standard) 
+	 */
+
+ 	ircomm_parse_control(self, skb, CONTROL_CHANNEL);
+
+	if(self->notify.data_indication && skb->len)
+		self->notify.data_indication(self->notify.instance, self,
+					     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");
+}
+
+
+/* 
+ * ----------------------------------------------------------------------
+ * Implementation of state chart,
+ * descrived in section 7.1 of the specification.
+ * ----------------------------------------------------------------------
+ */
+
+static void ircomm_do_event( struct ircomm_cb *self, IRCOMM_EVENT event,
+			     struct sk_buff *skb) {
+	
+	DEBUG( 4, "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) {
+	self->state = state;
+	DEBUG( 0, "ircomm_next_state: NEXT STATE = %d(%s), sv(%d)\n", 
+	       (int)state, ircommstate[self->state],self->servicetype);
+}
+
+
+/* 
+ * we currently need dummy (discovering) state for debugging,
+ * which state is not defined in the reference.
+ */
+
+static void ircomm_state_discovery( struct ircomm_cb *self,
+				    IRCOMM_EVENT event, struct sk_buff *skb ){
+	DEBUG(0,"ircomm_state_discovery: "
+	      "why call me? \n");
+	if(skb)
+		dev_kfree_skb( skb);
+}
+
+
+/*
+ * ircomm_state_idle
+ */
+
+static void ircomm_state_idle( struct ircomm_cb *self, IRCOMM_EVENT event, 
+			       struct sk_buff *skb ){
+	switch(event){
+	case IRCOMM_CONNECT_REQUEST:
+
+		ircomm_next_state(self, COMM_WAITI);
+		issue_connect_request( self, skb );
+		break;
+		
+	case TTP_CONNECT_INDICATION:
+
+		ircomm_next_state(self, COMM_WAITR);
+		connect_indication( self, self->qos, skb);
+		break;
+
+	case LMP_CONNECT_INDICATION:
+
+		/* I think this is already done in irlpt_event.c */
+
+		DEBUG(0,"ircomm_state_idle():LMP_CONNECT_IND is notimplemented!");
+ 		/* connect_indication_three_wire_raw(); */
+ 		/* ircomm_next_state(self, COMM_WAITR); */
+		break;
+
+	default:
+		DEBUG(0,"ircomm_state_idle():unknown event =%d(%s)\n",
+		      event, ircommevent[event]);
+	}
+}
+
+/*
+ * ircomm_state_waiti
+ */
+
+static void ircomm_state_waiti(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			  struct sk_buff *skb ){
+	switch(event){
+	case TTP_CONNECT_CONFIRM:
+		ircomm_next_state(self, COMM_CONN);
+		connect_confirmation( self, skb );
+		break;
+	case TTP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, COMM_IDLE);
+		disconnect_indication(self, skb);
+		break;
+/* 	case LMP_CONNECT_CONFIRM: */
+/* 		ircomm_connect_cnfirmation; */
+/* 		ircomm_next_state(self, COMM_CONN); */
+/* 		break; */
+/* 	case LMP_DISCONNECT_INDICATION: */
+/* 		ircomm_disconnect_ind; */
+/* 		ircomm_next_state(self, COMM_IDLE); */
+/* 		break; */
+	default:
+		DEBUG(0,"ircomm_state_waiti:unknown event =%d(%s)\n",
+		      event, ircommevent[event]);
+	}
+}
+
+
+
+/*
+ * ircomm_state_waitr
+ */
+static void ircomm_state_waitr(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			  struct sk_buff *skb ) {
+	
+	switch(event){
+	case IRCOMM_CONNECT_RESPONSE:
+
+	        /* issue_connect_response */
+		
+		if(self->servicetype==THREE_WIRE_RAW){
+			DEBUG(0,"ircomm:issue_connect_response:"
+			      "THREE_WIRE_RAW is not implemented!\n");
+			/* irlmp_connect_response(Vpeersap,
+			 *                         ACCEPT,null);
+			 */
+		} else {
+			ircomm_next_state(self, COMM_CONN);
+			issue_connect_response(self, skb);
+		}
+		break;
+
+	case IRCOMM_DISCONNECT_REQUEST:
+		ircomm_next_state(self, COMM_IDLE);
+		issue_disconnect_request(self, skb);
+		break;
+
+	case TTP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, COMM_IDLE);
+		disconnect_indication(self, skb);
+		break;
+
+/* 	case LMP_DISCONNECT_INDICATION: */
+/* 		disconnect_indication();		 */
+/* 		ircomm_next_state(self, COMM_IDLE);		 */
+/* 		break; */
+	default:
+		DEBUG(0,"ircomm_state_waitr:unknown event =%d(%s)\n",
+		      event, ircommevent[event]);
+	}
+}
+
+/*
+ * ircomm_state_conn
+ */
+
+static void ircomm_state_conn(struct ircomm_cb *self, IRCOMM_EVENT event, 
+			  struct sk_buff *skb ){
+	switch(event){
+	case TTP_DATA_INDICATION:
+		process_data(self, skb);
+		/* stay CONN state*/
+		break;
+	case IRCOMM_DATA_REQUEST:
+		issue_data_request(self, skb);
+		/* stay CONN state*/
+		break;
+/* 	case LMP_DATA_INDICATION: */
+/* 		ircomm_data_indicated(); */
+/* 		 stay CONN state */
+/* 		break; */
+	case IRCOMM_CONTROL_REQUEST:
+		issue_control_request(self, skb);
+		/* stay CONN state*/
+		break;
+	case TTP_DISCONNECT_INDICATION:
+		ircomm_next_state(self, COMM_IDLE);
+		disconnect_indication(self, skb);
+		break;
+	case IRCOMM_DISCONNECT_REQUEST:
+		ircomm_next_state(self, COMM_IDLE);
+		issue_disconnect_request(self, skb);
+		break;
+/* 	case LM_DISCONNECT_INDICATION: */
+/* 		disconnect_indication(); */
+/* 		ircomm_next_state(self, COMM_IDLE); */
+/* 		break; */
+	default:
+		DEBUG(0,"ircomm_state_conn:unknown event =%d(%s)\n",
+		      event, ircommevent[event]);
+	}
+}
+
+
+/*
+ *  ----------------------------------------------------------------------
+ *  ircomm requests
+ *
+ *  ----------------------------------------------------------------------
+ */
+
+
+void ircomm_connect_request(struct ircomm_cb *self, int maxsdusize){
+
+	/*
+	 * TODO:build a packet which contains "initial control parameters"
+	 * and send it with connect_request
+	 */
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+
+	DEBUG(0,"ircomm_connect_request:\n");
+
+	self->maxsdusize = maxsdusize;
+	ircomm_do_event( self, IRCOMM_CONNECT_REQUEST, NULL);
+}
+
+void ircomm_connect_response(struct ircomm_cb *self, struct sk_buff *userdata,
+			     int maxsdusize){
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+	/* ASSERT( userdata != NULL, return;); */
+
+	DEBUG(4,"ircomm_connect_response:\n");
+
+	/*
+	 * TODO:build a packet which contains "initial control parameters"
+	 * and send it with connect_response
+	 */
+
+	if(!userdata){
+		/* FIXME: check for errors and initialize? DB */
+		userdata = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+		if(!userdata){
+		  DEBUG(0, __FUNCTION__"alloc_skb failed\n");
+		  return;
+		}
+		IS_SKB(userdata, return;);
+		skb_reserve(userdata,COMM_HEADER_SIZE);
+	}
+
+	/* enable null-modem emulation (i.e. server mode )*/
+	self->null_modem_mode = 1;
+
+	self->maxsdusize = maxsdusize;
+	if(maxsdusize != SAR_DISABLE)
+		self->max_txbuff_size = maxsdusize;
+	ircomm_do_event(self, IRCOMM_CONNECT_RESPONSE, userdata);
+}	
+
+void ircomm_disconnect_request(struct ircomm_cb *self, struct sk_buff *userdata){
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+
+	DEBUG(0,"ircomm_disconnect_request\n");
+	ircomm_do_event(self, IRCOMM_DISCONNECT_REQUEST, NULL);
+}	
+
+
+void ircomm_data_request(struct ircomm_cb *self, struct sk_buff *userdata){
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+	ASSERT( userdata != NULL, return;);
+	
+	if(self->state != COMM_CONN){
+		DEBUG(4,"ignore IRCOMM_DATA_REQUEST:not connected\n");
+		if(userdata)
+			dev_kfree_skb(userdata);
+		return;
+	}
+
+	DEBUG(4,"ircomm_data_request\n");
+	ircomm_do_event(self, IRCOMM_DATA_REQUEST, userdata);
+}
+
+/*
+ *  ----------------------------------------------------------------------
+ *  IrCOMM_control.req and friends
+ *
+ *  ----------------------------------------------------------------------
+ */
+
+static void ircomm_tx_ctrlbuffer(struct ircomm_cb *self ){
+
+	__u8 clen;
+	struct sk_buff *skb = self->ctrl_skb;
+	
+	DEBUG(4,"ircomm_tx_ctrlbuffer:\n");
+
+	/* add "clen" field */
+
+	clen=skb->len;
+	if(clen){
+		skb_push(skb,1);
+		skb->data[0]=clen;
+
+#if 0
+	printk("tx_ctrl:");
+	{
+		int i;
+		for ( i=0;i<skb->len;i++)
+			printk("%02x", skb->data[i]);
+		printk("\n");
+	}
+#endif
+
+		ircomm_do_event(self, IRCOMM_CONTROL_REQUEST, skb);
+
+		skb = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE);
+		if (skb==NULL){
+			DEBUG(0,"ircomm_tx_ctrlbuffer:alloc_skb failed!\n");
+			return;
+		}
+		skb_reserve(skb,COMM_HEADER_SIZE);
+		self->ctrl_skb = skb;
+	}
+}
+
+
+void ircomm_control_request(struct ircomm_cb *self){
+	
+	struct sk_buff *skb;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+
+	DEBUG(0, "ircomm_control_request:\n");
+
+	if(self->ttp_stop || self->state != COMM_CONN){
+		DEBUG(0,"ircomm_control_request:can't send it.. ignore it\n");
+		return;
+	}
+	
+	skb = self->ctrl_skb;
+	IS_SKB(skb,return;);
+		
+	if(skb->len)
+		ircomm_tx_ctrlbuffer(self);
+}
+
+
+static void append_tuple(struct ircomm_cb *self,
+			 __u8 instruction, __u8 pl , __u8 *value){
+
+	__u8 *frame;
+	struct sk_buff *skb;
+	int i,c;
+
+	skb = self->ctrl_skb;
+	ASSERT(skb != NULL, return;);
+	IS_SKB(skb,return;);
+	
+	/*if there is little room in the packet... */
+
+	if(skb->len > COMM_DEFAULT_DATA_SIZE - COMM_HEADER_SIZE - (pl+2)){
+		if(!self->ttp_stop && self->state == COMM_CONN){
+
+			/* send a packet if we can */
+			ircomm_tx_ctrlbuffer(self);
+			skb = self->ctrl_skb;
+		} else {
+			DEBUG(0, "ircomm_append_ctrl:there's no room.. ignore it\n");
+
+			/* TODO: we have to detect whether we have to resend some
+			   information after ttp_stop is cleared */
+
+			/* self->resend_ctrl = 1; */
+			return;
+		}
+	}
+
+	frame = skb_put(skb,pl+2);
+	c = 0;
+	frame[c++] = instruction;     /* PI */
+	frame[c++] = pl;              /* PL */
+	for(i=0; i < pl ; i++)
+		frame[c++] = *value++;   /* PV */
+	
+}
+
+
+
+/*
+ * ircomm_append_ctrl();
+ * this function is exported as a request to send some control-channel tuples
+ * to peer device
+ */
+
+void ircomm_append_ctrl(struct ircomm_cb *self,  __u8 instruction){
+
+	__u8  pv[70];
+	__u8  *value = &pv[0];
+	__u32 temp;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRCOMM_MAGIC, return;);
+
+	if(self->state != COMM_CONN)
+		return;
+
+	if(self->servicetype == THREE_WIRE_RAW){
+		DEBUG(0,"THREE_WIRE_RAW shuold not use me!\n");
+		return;
+	}
+
+	DEBUG(4,"ircomm_append_ctrl:\n");
+
+	/* find parameter and its length */
+
+	switch(instruction){
+
+	case POLL_FOR_LINE_SETTINGS:
+	case STATUS_QUERY:
+	case IEEE1284_MODE_SUPPORT:
+	case IEEE1284_DEVICEID:
+		append_tuple(self,instruction,0,NULL);
+		break;
+
+	case SERVICETYPE:
+		value[0] = self->servicetype;
+		append_tuple(self,instruction,1,value);
+		break;
+	case DATA_FORMAT:
+		value[0] = self->data_format;
+		append_tuple(self,instruction,1,value);
+		break;
+	case FLOW_CONTROL:
+		if(self->null_modem_mode){
+
+			/* inside out */
+			value[0]  = (self->flow_ctrl & 0x55) << 1;
+			value[0] |= (self->flow_ctrl & 0xAA) >> 1;
+		}else{
+			value[0] = self->flow_ctrl;
+		}
+		append_tuple(self,instruction,1,value);
+		break;
+	case LINESTATUS:
+		value[0] = self->line_status;
+		append_tuple(self,instruction,1,value);
+		break;
+	case BREAK_SIGNAL:
+		value[0] = self->break_signal;
+		append_tuple(self,instruction,1,value);
+		break;
+	case DTELINE_STATE:		
+		if(self->null_modem_mode){
+			/* null modem emulation */
+
+			/* output RTS as CTS */
+
+			if(self->dte & DELTA_RTS)
+				value[0] = DELTA_CTS;
+			if(self->dte & MCR_RTS)
+				value[0] |= MSR_CTS;
+
+			/* output DTR as {DSR & CD & RI} */
+
+			if(self->dte & DELTA_DTR)
+				value[0] |= (DELTA_DSR|DELTA_RI|DELTA_DCD);
+			if(self->dte & MCR_DTR)
+				value[0] |= (MSR_DSR|MSR_RI|MSR_DCD);
+			append_tuple(self,DCELINE_STATE,1,value);
+		}else{
+			value[0] = self->dte;
+			append_tuple(self,instruction,1,value);
+		}
+		self->dte &= ~(DELTA_RTS|DELTA_DTR);
+		break;
+
+	case DCELINE_STATE:		
+		value[0] = self->dce;
+		append_tuple(self,instruction,1,value);
+		break;
+	case SET_BUSY_TIMEOUT:
+		value[0] = self->busy_timeout;
+		append_tuple(self,instruction,1,value);
+		break;
+
+	case XON_XOFF_CHAR:
+		value[0] = self->xon_char;
+		value[1] = self->xoff_char;
+		append_tuple(self,instruction,2,value); 
+		break; 
+
+	case ENQ_ACK_CHAR:
+		value[0] = self->enq_char;
+		value[1] = self->ack_char;
+		append_tuple(self,instruction,2,value); 
+		break; 
+
+ 	case IEEE1284_ECP_EPP_DATA_TRANSFER: 
+		value[0] = self->ecp_epp_mode;
+		value[1] = self->channel_or_addr;
+		append_tuple(self,instruction,2,value); 
+		break; 
+
+	case DATA_RATE:
+		temp = self->data_rate;
+		value[3] = (__u8)((temp >> 24) & 0x000000ff);
+		value[2] = (__u8)((temp >> 16) & 0x000000ff);
+		value[1] = (__u8)((temp >> 8) & 0x000000ff);
+		value[0] = (__u8)(temp & 0x000000ff);
+ 		append_tuple(self,instruction,4,value);
+ 		break;
+
+#if 0
+	case PORT_NAME:
+	case FIXED_PORT_NAME:
+		temp = strlen(&self->port_name);
+		if(temp < 70){
+			value = (__u8) (self->port_name);
+			append_tuple(self,instruction,temp,value);
+		}
+		break;
+#endif
+
+/* TODO: control tuples for centronics emulation is not implemented */
+/* 	case IEEE1284_MODE: */
+
+	default:
+		DEBUG(0,"ircomm_append_ctrl:instruction(0x%02x)is not"
+		      "implemented\n",instruction);
+	}
+
+
+}
+
+static void ircomm_parse_control(struct ircomm_cb *self,
+				 struct sk_buff *skb,
+				 int type){
+
+	__u8 *data;
+	__u8 pi,pl,pv[64];
+	int clen = 0;
+	int i,indicate,count = 0;
+
+	
+	data = skb->data;
+	if(type == IAS_PARAM) 
+		clen = ((data[count++] << 8) & data[count++]); /* MSB first */
+	else /* CONTROL_CHANNEL */
+		clen = data[count++];
+
+
+	if(clen == 0){
+		skb_pull( skb, 1);  /* remove clen field */
+		return;
+	}
+
+
+
+
+	while( count < clen ){
+		/* 
+		 * parse controlparameters and set value into structure 
+		 */
+		pi = data[count++];
+		pl = data[count++];
+			
+		DEBUG(0, "parse_control:instruction(0x%02x)\n",pi) ;
+
+
+		/* copy a tuple into pv[] */
+
+#ifdef IRCOMM_DEBUG_TUPLE
+		printk("data:");
+		for(i=0; i < pl; i++){
+			pv[i] = data[count++];
+			printk("%02x",pv[i]);
+		}
+		printk("\n");
+#else
+		for(i=0; i < pl; i++)
+			pv[i] = data[count++];
+#endif			
+		
+
+		/* parse pv */
+		indicate = 0;
+
+		switch(pi){
+			
+			/*
+			 * for 3-wire/9-wire/centronics
+			 */
+			
+		case SERVICETYPE:
+			self->peer_servicetype = pv[0];
+			break;
+		case PORT_TYPE:
+			self->peer_port_type = pv[0];
+			break;
+#if 0 
+		case PORT_NAME:
+			self->peer_port_name = *pv;
+			break;
+		case FIXED_PORT_NAME:
+			self->peer_port_name = *pv;
+			/* 
+			 * We should not connect if user of IrCOMM can't
+			 * recognize the port name
+			 */
+			self->port_name_critical = TRUE;
+			break;
+#endif
+		case DATA_RATE:     
+			self->peer_data_rate	= (pv[3]<<24) & (pv[2]<<16)
+				& (pv[1]<<8) & pv[0];
+			indicate = 1;
+			break;
+		case DATA_FORMAT:   
+			self->peer_data_format = pv[0];
+			break;
+		case FLOW_CONTROL:
+			self->peer_flow_ctrl = pv[0];
+			indicate = 1;
+			break;
+		case XON_XOFF_CHAR:
+			self->peer_xon_char = pv[0];
+			self->peer_xoff_char = pv[1];
+			indicate = 1;
+			break;
+		case ENQ_ACK_CHAR:
+			self->peer_enq_char = pv[0];
+			self->peer_ack_char = pv[1];
+			indicate = 1;
+			break;
+		case LINESTATUS:
+			self->peer_line_status = pv[0];
+			indicate = 1;
+			break;
+		case BREAK_SIGNAL:
+			self->peer_break_signal = pv[0];
+			/* indicate = 1; */
+			break;
+			
+			/*
+			 * for 9-wire
+			 */
+
+		case DTELINE_STATE:
+			if(self->null_modem_mode){
+				/* input DTR as {DSR & CD & RI} */
+				self->peer_dce = 0;
+				if(pv[0] & DELTA_DTR)
+					self->peer_dce |= DELTA_DSR|DELTA_RI|DELTA_DCD;
+				if(pv[0] & MCR_DTR)
+					self->peer_dce |= MSR_DSR|MSR_RI|MSR_DCD;
+
+				/* rts as cts */
+				if(pv[0] & DELTA_RTS)
+					self->peer_dce |= DELTA_CTS;
+				if(pv[0] & MCR_RTS)
+					self->peer_dce |= MSR_CTS;
+			}else{
+				self->peer_dte = pv[0];
+			}
+			indicate = 1;			
+			break;
+
+		case DCELINE_STATE:
+			self->peer_dce = pv[0];
+			indicate = 1;
+			break;
+
+		case POLL_FOR_LINE_SETTINGS:
+			ircomm_append_ctrl(self, DTELINE_STATE);
+			ircomm_control_request(self);
+			break;
+
+			/*
+			 * for centronics .... not implemented yet
+			 */
+/* 			case STATUS_QUERY: */
+/* 			case SET_BUSY_TIMEOUT: */
+/* 			case IEEE1284_MODE_SUPPORT: */
+/* 			case IEEE1284_DEVICEID: */
+/* 			case IEEE1284_MODE: */
+/* 			case IEEE1284_ECP_EPP_DATA_TRANSFER:	 */
+			
+		default:
+			DEBUG(0, "ircomm_parse_control:not implemented "
+			      "instruction(%d)\n", pi);
+			break;
+		}
+
+		if(indicate && self->notify.flow_indication 
+		   && type == CONTROL_CHANNEL){
+			
+			DEBUG(0,"ircomm:parse_control:indicating..:\n");
+			self->pi = pi;
+			if(self->notify.flow_indication)
+				self->notify.flow_indication(self->notify.instance, self, 0);
+			indicate = 0;
+		}
+	}
+	skb_pull( skb, 1+clen);
+	return;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * Function init_module(void) ,cleanup_module()
+ *
+ *   Initializes the ircomm control structure
+ *   These Function are called when you insmod / rmmod .
+ * ----------------------------------------------------------------------
+ */
+
+#ifdef MODULE
+
+int init_module(void) {
+	ircomm_init();
+
+	DEBUG( 4, "ircomm:init_module:done\n");
+	return 0;
+}
+	
+void cleanup_module(void)
+{
+	ircomm_cleanup();
+	DEBUG( 0, "ircomm_common:cleanup_module:done.\n");
+}
+
+#endif /* MODULE */
+
+/************************************************************
+ *     proc stuff
+ ************************************************************/
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Function proc_ircomm_read (buf, start, offset, len, unused)
+ *
+ * this function is called if there is a access on /proc/irda/comm .
+ *
+ */
+int ircomm_proc_read(char *buf, char **start, off_t offset,
+		     int len, int unused){
+	int i, index;
+
+	len = 0;
+	for (i=0; i<IRCOMM_MAX_CONNECTION; i++) {
+
+		if (ircomm[i] == NULL || ircomm[i]->magic != IRCOMM_MAGIC) {
+			len += sprintf(buf+len, "???\t");
+		}else {
+			switch (ircomm[i]->servicetype) {
+			case UNKNOWN:
+				index = 0;
+				break;
+			case THREE_WIRE_RAW:
+				index = 1;
+				break;
+			case THREE_WIRE:
+				index = 2;
+				break;
+			case NINE_WIRE:
+				index = 3;
+				break;
+			case CENTRONICS:
+				index = 4;
+				break;
+			default:
+				index = 0;
+				break;
+			}
+			len += sprintf(buf+len, "service: %s\t",
+				       ircommservicetype[index]);
+			if(index){
+				len += sprintf(buf+len, "porttype: %s  ",
+					       ircommporttype[ircomm[i]->port_type]);
+				len += sprintf(buf+len, "state: %s  ",
+					       ircommstate[ircomm[i]->state]);
+				len += sprintf(buf+len, "user: %s  ",
+					       ircomm[i]->notify.name);
+				len += sprintf(buf+len, "nullmodem emulation: %s",
+					       (ircomm[i]->null_modem_mode ? "yes":"no"));
+			}
+		}
+		len += sprintf(buf+len, "\n");
+	}
+	return len;
+}
+
+
+#endif /* CONFIG_PROC_FS */
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/ircomm/irvtd.c linux/net/irda/ircomm/irvtd.c
--- v2.1.131/linux/net/irda/ircomm/irvtd.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/irvtd.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,153 @@
+/*********************************************************************
+ *                
+ * Filename:      irvtd.c
+ * Version:       
+ * Description:   A virtual tty driver implementaion,
+ *                which also may be called as "Port Emulation Entity"
+ *                in IrCOMM specification.
+ * Status:        Experimental.
+ * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
+ * Source:        irlpt.c
+ *
+ *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+/* #include <linux/module.h> */
+
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+
+#include <net/irda/irvtd.h>
+#include <net/irda/irvtd_driver.h>
+
+struct irvtd_cb **irvtd = NULL;
+extern struct ircomm_cb **ircomm;
+
+#if 0
+static char *rcsid = "$Id: irvtd.c,v 1.2 1998/09/27 08:37:04 takahide Exp $";
+#endif
+static char *version = "IrVTD, $Revision: 1.2 $ $Date: 1998/09/27 08:37:04 $ (Takahide Higuchi)";
+
+
+/************************************************************
+ *    init & cleanup this module 
+ ************************************************************/
+
+/*
+ * Function init_module(void)
+ *
+ *   Initializes the ircomm control structure
+ *   This Function is called when you do insmod.
+ */
+
+__initfunc(int irvtd_init(void))
+{
+	int i;
+
+	DEBUG( 4, "irvtd:init_module:\n");
+	printk( KERN_INFO "%s\n", version);
+
+	/* we allocate master array */
+
+	irvtd = (struct irvtd_cb **) kmalloc( sizeof(void *) *
+						COMM_MAX_TTY,GFP_KERNEL);
+	if ( irvtd == NULL) {
+		printk( KERN_WARNING "irvtd: Can't allocate array!\n");
+		return -ENOMEM;
+	}
+
+	memset( irvtd, 0, sizeof(void *) * COMM_MAX_TTY);
+
+
+	/* we initialize structure */
+
+	for (i=0; i < COMM_MAX_TTY; i++){
+		irvtd[i] = kmalloc( sizeof(struct irvtd_cb), GFP_KERNEL);	
+		if(irvtd[i] == NULL){
+			printk(KERN_ERR "ircomm_open(): kmalloc failed!\n");
+			return -ENOMEM;
+		}
+
+		memset( irvtd[i], 0, sizeof(struct irvtd_cb));
+		irvtd[i]->magic = IRVTD_MAGIC;
+	}
+
+	/* 
+	 * initialize a "port emulation entity"
+	 */
+
+	if(irvtd_register_ttydriver()){
+		printk( KERN_WARNING "IrCOMM: Error in ircomm_register_device\n");
+		return -ENODEV;
+	}
+
+
+	DEBUG( 4, "irvtd:init_module:done\n");
+	return 0;
+}
+
+void irvtd_cleanup(void)
+{
+	int i;
+	DEBUG( 4, "--> ircomm:cleanup_module\n");
+
+	/*
+	 * free some resources
+	 */
+	if (irvtd) {
+		for (i=0; i<COMM_MAX_TTY; i++) {
+			if (irvtd[i]) {
+				DEBUG( 4, "freeing structures\n");
+				/* irvtd_close();  :{| */
+				kfree(irvtd[i]);
+				irvtd[i] = NULL;
+			}
+		}
+		DEBUG( 4, "freeing master array\n");
+		kfree(irvtd);
+		irvtd = NULL;
+	}
+
+
+
+	DEBUG( 0, "unregister_ttydriver..\n");
+ 	irvtd_unregister_ttydriver();
+
+	DEBUG( 4, "ircomm:cleanup_module -->\n");
+}
+
+#ifdef MODULE
+
+int init_module(void) 
+{
+	irvtd_init();
+	return 0;
+}
+
+
+/*
+ * Function ircomm_cleanup (void)
+ *   This is called when you rmmod.
+ */
+
+void cleanup_module(void)
+{
+	irvtd_cleanup();
+}
+
+#endif /* MODULE */
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/ircomm/irvtd_driver.c linux/net/irda/ircomm/irvtd_driver.c
--- v2.1.131/linux/net/irda/ircomm/irvtd_driver.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/ircomm/irvtd_driver.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1869 @@
+/*********************************************************************
+ *                
+ * Filename:      irvtd_driver.c
+ * Version:       
+ * Description:   An implementation of "port emulation entity" of IrCOMM
+ * Status:        Experimental.
+ * Author:        Takahide Higuchi <thiguchi@pluto.dti.ne.jp>
+ * Source:        serial.c by Linus Torvalds
+ *                isdn_tty.c by Fritz Elfert
+ *
+ *     Copyright (c) 1998, Takahide Higuchi, <thiguchi@pluto.dti.ne.jp>,
+ *     All Rights Reserved.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     I, Takahide Higuchi, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/termios.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irttp.h>
+
+#include <net/irda/irvtd.h>
+#include <net/irda/irvtd_driver.h>
+
+#ifndef MIN
+#define MIN(a,b)        ((a) < (b) ? (a) : (b))
+#endif
+
+#define DO_RESTART
+#define RELEVANT_IFLAG(iflag) (iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK))
+
+static char *irvtd_ttyname = "irnine";
+struct tty_driver irvtd_drv, irvtd_callout_driver;
+struct tty_struct *irvtd_table[COMM_MAX_TTY];
+struct termios *irvtd_termios[COMM_MAX_TTY];
+struct termios *irvtd_termios_locked[COMM_MAX_TTY];
+static int ircomm_vsd_refcount;
+extern struct ircomm_cb **ircomm;
+extern struct irvtd_cb **irvtd;
+
+/*
+ * prototypes
+ */
+
+int irvtd_open(struct tty_struct *tty, struct file *filp);
+void irvtd_close(struct tty_struct * tty, struct file * filp);
+int irvtd_write(struct tty_struct * tty, int from_user,
+			const unsigned char *buf, int count);
+void irvtd_put_char(struct tty_struct *tty, unsigned char ch);
+int irvtd_write_room(struct tty_struct *tty);
+int irvtd_chars_in_buffer(struct tty_struct *tty);
+int irvtd_ioctl(struct tty_struct *tty, struct file * file,
+	     unsigned int cmd, unsigned long arg);
+void irvtd_set_termios(struct tty_struct *tty, struct termios * old);
+void irvtd_throttle(struct tty_struct *tty);
+void irvtd_unthrottle(struct tty_struct *tty);
+void irvtd_stop(struct tty_struct *tty);
+void irvtd_start(struct tty_struct *tty);
+void irvtd_hangup(struct tty_struct *tty);
+void irvtd_flush_buffer(struct tty_struct *tty);
+
+static void flush_txbuff(struct irvtd_cb *info);
+static void change_speed(struct irvtd_cb *driver);
+static void irvtd_write_to_tty( void *instance );
+
+static void irvtd_break(struct tty_struct *tty, int break_state);
+static void irvtd_send_xchar(struct tty_struct *tty, char ch);
+
+#if 0
+static char *rcsid = "$Id: irvtd_driver.c,v 1.13 1998/12/06 10:09:07 takahide Exp $";
+#endif
+
+
+
+
+/*
+ * Function ircomm_register_device(void) 
+ *   we register "port emulation entity"(see IrCOMM specification) here
+ *   as a tty device.
+ *   it will be called when you insmod.
+ *   ( This function derives from linux/drivers/char/serial.c )
+ */
+
+int irvtd_register_ttydriver(void){
+
+        DEBUG( 4, "-->irvtd_register_ttydriver\n");
+
+	/* setup virtual serial port device */
+
+        /* Initialize the tty_driver structure ,which is defined in 
+	   tty_driver.h */
+        
+        memset(&irvtd_drv, 0, sizeof(struct tty_driver));
+	irvtd_drv.magic = IRVTD_MAGIC;
+	irvtd_drv.name = irvtd_ttyname;
+	irvtd_drv.major = IRCOMM_MAJOR;
+	irvtd_drv.minor_start = IRVTD_MINOR;
+	irvtd_drv.num = COMM_MAX_TTY;
+	irvtd_drv.type = TTY_DRIVER_TYPE_SERIAL;  /* see tty_driver.h */
+	irvtd_drv.subtype = IRVTD_TYPE_NORMAL;      /* private type */
+
+	/*
+	 * see drivers/char/tty_io.c and termios(3)
+	 */
+
+        irvtd_drv.init_termios = tty_std_termios;
+        irvtd_drv.init_termios.c_cflag =
+		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+        irvtd_drv.flags = TTY_DRIVER_REAL_RAW;   /* see tty_driver.h */
+        irvtd_drv.refcount = &ircomm_vsd_refcount;
+
+	/* pointer to the tty data structures */
+
+        irvtd_drv.table = irvtd_table;  
+        irvtd_drv.termios = irvtd_termios;
+        irvtd_drv.termios_locked = irvtd_termios_locked;
+
+        /*
+         * Interface table from the kernel(tty driver) to the ircomm
+         * layer
+         */
+
+        irvtd_drv.open = irvtd_open;
+        irvtd_drv.close = irvtd_close;
+        irvtd_drv.write = irvtd_write;
+        irvtd_drv.put_char = irvtd_put_char;
+	irvtd_drv.flush_chars = irvtd_flush_chars;
+        irvtd_drv.write_room = irvtd_write_room;
+	irvtd_drv.chars_in_buffer = irvtd_chars_in_buffer; 
+        irvtd_drv.flush_buffer = irvtd_flush_buffer;
+ 	irvtd_drv.ioctl = irvtd_ioctl; 
+	irvtd_drv.throttle = irvtd_throttle;
+	irvtd_drv.unthrottle = irvtd_unthrottle;
+ 	irvtd_drv.set_termios = irvtd_set_termios;
+	irvtd_drv.stop = NULL;          /*  irvtd_stop; */
+	irvtd_drv.start = NULL;         /* irvtd_start; */
+        irvtd_drv.hangup = irvtd_hangup;
+
+        irvtd_drv.send_xchar = irvtd_send_xchar;
+	irvtd_drv.break_ctl = irvtd_break;
+	irvtd_drv.read_proc = NULL;
+	irvtd_drv.wait_until_sent = NULL;
+
+        /*
+         * The callout device is just like normal device except for
+         * minor number and the subtype.
+         */
+
+	/* What is difference between callout device and normal device? */
+	/* My system dosen't have /dev/cua??, so we don't need it? :{| */
+	irvtd_callout_driver = irvtd_drv;
+	irvtd_callout_driver.name = "irninecua";
+	irvtd_callout_driver.minor_start = IRVTD_CALLOUT_MINOR; 
+	irvtd_callout_driver.subtype = IRVTD_TYPE_CALLOUT;
+
+
+	if (tty_register_driver(&irvtd_drv)){
+		DEBUG(0,"IrCOMM:Couldn't register tty driver\n");
+		return(1);
+	}
+	if (tty_register_driver(&irvtd_callout_driver))
+		DEBUG(0,"IrCOMM:Couldn't register callout tty driver\n");
+
+	DEBUG( 4, "irvtd_register_ttydriver: done.\n");
+	return(0);
+}
+
+
+/*
+ * Function irvtd_unregister_device(void) 
+ *   it will be called when you rmmod
+ */
+
+void irvtd_unregister_ttydriver(void){
+
+	int err;	
+        DEBUG( 4, "--> irvtd_unregister_device\n");
+
+	/* unregister tty device   */
+
+	err = tty_unregister_driver(&irvtd_drv);
+        if (err)
+                printk("IrCOMM: failed to unregister vtd driver(%d)\n",err);
+	err = tty_unregister_driver(&irvtd_callout_driver);
+        if (err)
+                printk("IrCOMM: failed to unregister vtd_callout driver(%d)\n", err);
+
+        DEBUG( 4, "irvtd_unregister_device -->\n");
+	return;
+}
+
+
+
+/*
+ * ----------------------------------------------------------------------
+ * Routines for Virtual tty driver
+ *
+ *   most of infomation is descrived in linux/tty_driver.h, but
+ *   a function ircomm_receive() derives from receive_chars() which is
+ *   in 2.0.30 kernel (driver/char/serial.c).
+ *   if you want to understand them, please see related kernel source 
+ *   (and my comments :).
+ * ----------------------------------------------------------------------
+ */
+
+/*
+ * ----------------------------------------------------------------------
+ * ircomm_receive_data()
+ *
+ * like interrupt handler in the serial.c,we receive data when 
+ * ircomm_data_indication comes
+ * ----------------------------------------------------------------------
+ */
+
+
+
+/* 
+ * irvtd_write_to_tty
+ * send incoming/queued data to tty
+ */
+
+static void irvtd_write_to_tty( void *instance ){
+	
+	int status, c, flag;
+	
+	struct sk_buff *skb;
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+	struct tty_struct *tty = driver->tty;
+	
+	/* does instance still exist ? should be checked */
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+	
+	if(driver->rx_disable ){
+		DEBUG(0,__FUNCTION__"rx_disable is true:do_nothing..\n");
+		return;
+	}
+	
+	skb = skb_dequeue(&driver->rxbuff);
+	ASSERT(skb != NULL, return;); /* there's nothing */
+	IS_SKB(skb, return;);
+	
+#ifdef IRVTD_DEBUG_RX
+	printk("received data:");
+	{
+		int i;
+		for ( i=0;i<skb->len;i++)
+			printk("%02x ", skb->data[i]);
+		printk("\n");
+	}
+#endif
+	
+	status = driver->comm->peer_line_status & driver->read_status_mask;
+	
+	/* 
+	 * FIXME: we must do ircomm_parse_ctrl() here, instead of 
+	 * ircomm_common.c!! 
+	 */
+	
+
+	/* 
+	 * if there are too many errors which make a character ignored,
+	 * drop characters
+	 */
+
+	if(status & driver->ignore_status_mask){
+		DEBUG(0,__FUNCTION__":some error:ignore characters.\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+	
+	c = MIN(skb->len, (TTY_FLIPBUF_SIZE - tty->flip.count));
+	DEBUG(4, __FUNCTION__"skb_len=%d, tty->flip.count=%d \n"
+	      ,(int)skb->len, tty->flip.count);
+	
+	if (driver->comm->peer_break_signal ) {
+		driver->comm->peer_break_signal = 0;
+		DEBUG(0,"handling break....\n");
+		
+		flag = TTY_BREAK;
+		if (driver->flags & IRVTD_ASYNC_SAK)
+			/*
+			 * do_SAK() seems to be an implementation of the 
+			 * idea called "Secure Attention Key",
+			 * which seems to be discribed in "Orange book".
+			 * (which is published by U.S.military!!?? ,
+			 * see source of do_SAK())
+			 *
+			 * but what kind of security do we need 
+			 * when we use infrared communication??? :p)
+			 */
+			do_SAK(tty);
+	}else if (status & LSR_PE)
+		flag = TTY_PARITY;
+	else if (status & LSR_FE)
+		flag = TTY_FRAME;
+	else if (status & LSR_OE)
+		flag = TTY_OVERRUN;
+	else 
+		flag = TTY_NORMAL;
+	
+	if(c){
+		DEBUG(0,"writing %d chars to tty\n",c);
+		memset(tty->flip.flag_buf_ptr, flag, c);
+		memcpy(tty->flip.char_buf_ptr, skb->data, c);
+		tty->flip.flag_buf_ptr += c;
+		tty->flip.char_buf_ptr += c;
+		tty->flip.count += c;
+		skb_pull(skb,c);
+	}
+
+	if(skb->len == 0)
+		dev_kfree_skb(skb);
+	else
+	{
+		/* queue rest of data again */
+		DEBUG(0,__FUNCTION__":retrying frame!\n");
+		skb_queue_head( &driver->rxbuff, skb );
+	}
+	
+	/*
+	 * in order to optimize this routine, these two tasks should be
+	 * queued in following order
+	 * ( see run_task_queue() and queue_task() in tqueue.h
+	 */
+	if(skb_queue_len(&driver->rxbuff))
+		/* let me try again! */
+		queue_task(&driver->rx_tqueue, &tq_timer);
+	if(c)
+		/* read your buffer! */
+		queue_task(&tty->flip.tqueue, &tq_timer);
+	
+
+	if(skb_queue_len(&driver->rxbuff)< IRVTD_RX_QUEUE_LOW
+	   &&  driver->ttp_stoprx){
+		irttp_flow_request(driver->comm->tsap, FLOW_START);
+		driver->ttp_stoprx = 0;
+	}
+}
+
+void irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb){
+	
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+
+	/* queue incoming data and make bottom half handler ready */
+
+	skb_queue_tail( &driver->rxbuff, skb );
+	if(skb_queue_len(&driver->rxbuff) == 1)
+		irvtd_write_to_tty(driver);
+	if(skb_queue_len(&driver->rxbuff) > IRVTD_RX_QUEUE_HIGH){
+		irttp_flow_request(driver->comm->tsap, FLOW_STOP);
+		driver->ttp_stoprx = 1;
+	}
+	return;
+}
+
+#if 0
+void irvtd_receive_data(void *instance, void *sap, struct sk_buff *skb){
+	
+	int flag,status;
+	__u8 c;
+	struct tty_struct *tty;
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+
+	if(driver->rx_disable ){
+		DEBUG(0,__FUNCTION__"rx_disable is true:do nothing\n");
+		return;
+	}
+
+	tty = driver->tty;
+	status = driver->comm->peer_line_status & driver->read_status_mask;
+
+	c = MIN(skb->len, (TTY_FLIPBUF_SIZE - tty->flip.count));
+	DEBUG(0, __FUNCTION__"skb_len=%d, tty->flip.count=%d \n"
+	      ,(int)skb->len, tty->flip.count);
+
+#ifdef IRVTD_DEBUG_RX
+	printk("received data:");
+	{
+		int i;
+		for ( i=0;i<skb->len;i++)
+			printk("%02x ", skb->data[i]);
+		printk("\n");
+	}
+#endif
+
+	/* 
+	 * if there are too many errors which make a character ignored,
+	 * drop characters
+	 */
+
+	if(status & driver->ignore_status_mask){
+		DEBUG(0,__FUNCTION__"I/O error:ignore characters.\n");
+		dev_kfree_skb(skb, FREE_READ);
+		return;
+	} 
+	
+	if (driver->comm->peer_break_signal ) {
+		driver->comm->peer_break_signal = 0;
+		DEBUG(0,"handling break....\n");
+		
+		flag = TTY_BREAK;
+		if (driver->flags & IRVTD_ASYNC_SAK)
+			/*
+			 * do_SAK() seems to be an implementation of the 
+			 * idea called "Secure Attention Key",
+			 * which seems to be discribed in "Orange book".
+			 * (which is published by U.S.military!!?? )
+			 * see source of do_SAK() but what is "Orange book"!?
+			 */
+			do_SAK(tty);
+	}else if (status & LSR_PE)
+		flag = TTY_PARITY;
+	else if (status & LSR_FE)
+		flag = TTY_FRAME;
+	else if (status & LSR_OE)
+		flag = TTY_OVERRUN;
+	else 
+		flag = TTY_NORMAL;
+
+	if(c){
+		DEBUG(0,"writing %d chars to tty\n",c);
+		memset(tty->flip.flag_buf_ptr, flag, c);
+		memcpy(tty->flip.char_buf_ptr, skb->data, c);
+		tty->flip.flag_buf_ptr += c;
+		tty->flip.char_buf_ptr += c;
+		tty->flip.count += c;
+		skb_pull(skb,c);
+		queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+	}
+	if(skb->len >0)
+		DEBUG(0,__FUNCTION__":dropping frame!\n");
+	dev_kfree_skb(skb, FREE_READ);
+	DEBUG(4,__FUNCTION__":done\n");
+}
+#endif
+
+/*
+ * ----------------------------------------------------------------------
+ * indication/confirmation handlers:
+ * they will be registerd in irvtd_startup() to know that we
+ * discovered (or we are discovered by) remote device.
+ * ----------------------------------------------------------------------
+ */
+
+/* this function is called whed ircomm_attach_cable succeed */
+
+void irvtd_attached(struct ircomm_cb *comm){
+
+	ASSERT(comm != NULL, return;);
+	ASSERT(comm->magic == IRCOMM_MAGIC, return;);
+
+	DEBUG(0,"irvtd_attached:sending connect_request"
+	      " for servicetype(%d)..\n",comm->servicetype);
+	ircomm_connect_request(comm, SAR_DISABLE );
+}
+
+
+/*
+ * irvtd_connect_confirm()
+ *  ircomm_connect_request which we have send have succeed!
+ */
+
+void irvtd_connect_confirm(void *instance, void *sap, struct qos_info *qos,
+			   int max_sdu_size, struct sk_buff *skb){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+
+	/*
+	 * sending initial control parameters here
+	 *
+	 * TODO: it must be done in ircomm_connect_request()
+	 */
+#if 1
+	if(driver->comm->servicetype ==	THREE_WIRE_RAW)
+		return;                /* do nothing */
+
+	ircomm_append_ctrl(driver->comm, SERVICETYPE);
+	/* ircomm_append_ctrl(self, DATA_RATE); */
+	ircomm_append_ctrl(driver->comm, DATA_FORMAT);
+	ircomm_append_ctrl(driver->comm, FLOW_CONTROL);
+	ircomm_append_ctrl(driver->comm, XON_XOFF_CHAR);
+	/* ircomm_append_ctrl(driver->comm, ENQ_ACK_CHAR); */
+
+	switch(driver->comm->servicetype){
+	case CENTRONICS:
+		break;
+
+	case NINE_WIRE:
+		ircomm_append_ctrl(driver->comm, DTELINE_STATE);
+		break;
+	default:
+	}
+	ircomm_control_request(driver->comm);
+#endif
+	
+
+	wake_up_interruptible(&driver->open_wait);
+}
+
+/*
+ * irvtd_connect_indication()
+ *  we are discovered and being requested to connect by remote device !
+ */
+
+void irvtd_connect_indication(void *instance, void *sap, struct qos_info *qos,
+			      int max_sdu_size, struct sk_buff *skb)
+{
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+	struct ircomm_cb *comm = (struct ircomm_cb *)sap;
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+	ASSERT(comm != NULL, return;);
+	ASSERT(comm->magic == IRCOMM_MAGIC, return;);
+
+	DEBUG(4,"irvtd_connect_indication:sending connect_response...\n");
+
+	/*TODO: connect_response should send initialcontrolparameters! TH*/
+
+	ircomm_connect_response(comm, NULL, SAR_DISABLE );
+
+	wake_up_interruptible(&driver->open_wait);
+}
+
+
+
+void irvtd_disconnect_indication(void *instance, void *sap , LM_REASON reason,
+				 struct sk_buff *skb){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->tty != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+
+	DEBUG(4,"irvtd_disconnect_indication:\n");
+	tty_hangup(driver->tty);
+}
+
+/*
+ * irvtd_control_indication
+ *
+ */
+
+
+void irvtd_control_indication(void *instance, void *sap, LOCAL_FLOW flow){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)instance;
+	__u8 pi; /* instruction of control channel */
+
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+
+	DEBUG(0,"irvtd_control_indication:\n");
+
+	pi = driver->comm->pi;
+
+	switch(pi){
+
+	case DCELINE_STATE:
+	driver->msr = driver->comm->peer_dce;
+
+	if(driver->msr & (DELTA_CTS|DELTA_DSR|DELTA_RI|DELTA_DCD)){
+		if(driver->msr & DELTA_CTS)
+			driver->icount.cts++;
+		if(driver->msr & DELTA_DSR)
+			driver->icount.dsr++;
+		if(driver->msr & DELTA_RI)
+			driver->icount.rng++;
+		if(driver->msr & DELTA_DCD)
+			driver->icount.dcd++;
+		wake_up_interruptible(&driver->delta_msr_wait);
+	}
+
+	if ((driver->flags & IRVTD_ASYNC_CHECK_CD) && (driver->msr & DELTA_DCD)) {
+
+		DEBUG(0,"CD now %s...\n",
+		      (driver->msr & MSR_DCD) ? "on" : "off");
+
+		if (driver->msr & DELTA_DCD)
+			wake_up_interruptible(&driver->open_wait);
+		else if (!((driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) &&
+			   (driver->flags & IRVTD_ASYNC_CALLOUT_NOHUP))) {
+
+                        DEBUG(0,"irvtd_control_indication:hangup..\n");
+			tty_hangup(driver->tty);
+		}
+	}
+
+	if (driver->comm->flow_ctrl & USE_CTS) {
+		if (driver->tty->hw_stopped) {
+			if (driver->msr & MSR_CTS) {
+				DEBUG(0,"CTS tx start...\n");
+
+				driver->cts_stoptx = 0;
+				driver->tty->hw_stopped = driver->ttp_stoptx;
+				/*  
+				 * replacement of 
+				 * rs_sched_event(info, RS_EVENT_WRITE_WAKEUP)
+				 * in serial.c
+				 */
+
+				if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+				    driver->tty->ldisc.write_wakeup)
+					(driver->tty->ldisc.write_wakeup)(driver->tty);
+
+				wake_up_interruptible(&driver->tty->write_wait);
+				return;
+			}
+		} else {
+			if (!(driver->msr & MSR_CTS)) {
+				DEBUG(0,"CTS tx stop...");
+
+				driver->cts_stoptx = 1;
+				driver->tty->hw_stopped = 1;
+/* 				driver->IER &= ~UART_IER_THRI; */
+/* 				serial_out(info, UART_IER, info->IER); */
+                        }
+                }
+        }
+
+
+	break;
+
+	case TX_READY:
+		driver->ttp_stoptx = 0;
+		driver->tty->hw_stopped = driver->cts_stoptx;
+
+		/* 
+		 * driver->tty->write_wait will keep asleep if
+		 * our txbuff is not empty.
+		 * so if we can really send a packet now,
+		 * send it and then wake it up.
+		 */
+
+		if(driver->cts_stoptx)
+			break;
+
+		flush_txbuff(driver);
+		if ((driver->tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
+		     driver->tty->ldisc.write_wakeup)
+			(driver->tty->ldisc.write_wakeup)(driver->tty);
+		break;
+
+	case TX_BUSY:
+		driver->ttp_stoptx = driver->tty->hw_stopped = 1;
+		break;
+	default:
+		DEBUG(0,"irvtd:unknown control..\n");
+	
+	}
+}
+
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_open() and friends
+ *
+ * 
+ * ----------------------------------------------------------------------
+ */
+
+
+static int irvtd_block_til_ready(struct tty_struct *tty, struct file * filp,
+				 struct irvtd_cb *driver)
+{
+
+ 	struct wait_queue wait = { current, NULL };
+	int		retval;
+	int		do_clocal = 0;
+
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * (sleep) until it's done, and (when being woke up)then try again.
+	 */
+
+	if (tty_hung_up_p(filp) ||
+	    (driver->flags & IRVTD_ASYNC_CLOSING)) {
+		if (driver->flags & IRVTD_ASYNC_CLOSING)
+			interruptible_sleep_on(&driver->close_wait);
+#ifdef DO_RESTART
+		if (driver->flags & IRVTD_ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+
+	if (tty->driver.subtype == IRVTD_TYPE_CALLOUT) {
+		if (driver->flags & IRVTD_ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) &&
+		    (driver->flags & IRVTD_ASYNC_SESSION_LOCKOUT) &&
+		    (driver->session != current->session))
+			return -EBUSY;
+		if ((driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) &&
+		    (driver->flags & IRVTD_ASYNC_PGRP_LOCKOUT) &&
+		    (driver->pgrp != current->pgrp))
+			return -EBUSY;
+
+		driver->flags |= IRVTD_ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+
+		driver->flags |= IRVTD_ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+
+	if (driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) {
+		if (driver->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+	
+	/*
+	 * We wait until ircomm_connect_request() succeed or
+	 *   ircomm_connect_indication comes
+	 *
+	 * This is what is written in serial.c:
+	 * "Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, driver->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal."
+	 */
+
+	retval = 0;
+	add_wait_queue(&driver->open_wait, &wait);
+
+	DEBUG(0,"block_til_ready before block: line%d, count = %d\n",
+	       driver->line, driver->count);
+
+	cli();
+	if (!tty_hung_up_p(filp)) 
+		driver->count--;
+	sti();
+	driver->blocked_open++;
+
+
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+
+	if (!(driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) &&
+	    (driver->comm->state == COMM_CONN)){
+		/* 
+		 * signal DTR and RTS
+		 */
+		driver->comm->dte = driver->mcr |= (MCR_DTR | MCR_RTS |DELTA_DTR|DELTA_RTS);
+
+		ircomm_append_ctrl(driver->comm, DTELINE_STATE);
+		ircomm_control_request(driver->comm);
+	}
+
+		if (tty_hung_up_p(filp) ||
+		    !(driver->flags & IRVTD_ASYNC_INITIALIZED)) {
+#ifdef DO_RESTART
+			if (driver->flags & IRVTD_ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+
+		/*
+		 * if clocal == 0 or received DCD or state become CONN,then break
+		 */
+
+		if (!(driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE) &&
+		    !(driver->flags & IRVTD_ASYNC_CLOSING) &&
+		    (driver->comm->state == COMM_CONN) && 
+		    ( do_clocal || (driver->msr & MSR_DCD) )
+		    )
+			break;
+
+		if(signal_pending(current)){
+			retval = -ERESTARTSYS;
+			break;
+		}
+
+#ifdef IRVTD_DEBUG_OPEN
+		printk(KERN_INFO"block_til_ready blocking:"
+		       " ttys%d, count = %d\n", driver->line, driver->count);
+#endif
+		schedule();
+	}
+
+	current->state = TASK_RUNNING;
+	remove_wait_queue(&driver->open_wait, &wait);
+
+	if (!tty_hung_up_p(filp))
+		driver->count++;
+	driver->blocked_open--;
+#ifdef IRVTD_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttys%d, count = %d\n",
+	       driver->line, driver->count);
+#endif
+	if (retval)
+		return retval;
+	driver->flags |= IRVTD_ASYNC_NORMAL_ACTIVE;
+	return 0;
+}	
+
+static void change_speed(struct irvtd_cb *driver){
+
+	unsigned cflag,cval;
+
+	if (!driver->tty || !driver->tty->termios || !driver->comm)
+		return;
+	cflag = driver->tty->termios->c_cflag;
+
+
+
+	/*
+	 * change baud rate here. but not implemented now
+	 */
+
+
+
+
+	/* 
+	 * byte size and parity
+	 */
+	switch (cflag & CSIZE) {
+	      case CS5: cval = 0x00; break;
+	      case CS6: cval = 0x01; break;
+	      case CS7: cval = 0x02; break;
+	      case CS8: cval = 0x03; break;
+	      default:  cval = 0x00; break;	/* too keep GCC shut... */
+	}
+	if (cflag & CSTOPB) {      /* use 2 stop bit mode */
+		cval |= 0x04;
+	}
+	if (cflag & PARENB)
+		cval |= 0x08;
+	if (!(cflag & PARODD))
+		cval |= 0x10;
+	
+	/* CTS flow control flag and modem status interrupts */
+
+	if (cflag & CRTSCTS)
+		driver->comm->flow_ctrl |= USE_CTS;
+	else
+		driver->comm->flow_ctrl |= ~USE_CTS;
+	
+	if (cflag & CLOCAL)
+		driver->flags &= ~IRVTD_ASYNC_CHECK_CD;
+	else
+		driver->flags |= IRVTD_ASYNC_CHECK_CD;
+	
+	/*
+	 * Set up parity check flag
+	 */
+
+	driver->read_status_mask = LSR_OE ;
+	if (I_INPCK(driver->tty))
+		driver->read_status_mask |= LSR_FE | LSR_PE;
+	if (I_BRKINT(driver->tty) || I_PARMRK(driver->tty))
+		driver->read_status_mask |= LSR_BI;
+	
+	driver->ignore_status_mask = 0;
+
+	if (I_IGNBRK(driver->tty)) {
+		driver->ignore_status_mask |= LSR_BI;
+		driver->read_status_mask |= LSR_BI;
+		/*
+		 * If we're ignore parity and break indicators, ignore 
+		 * overruns too.  (For real raw support).
+		 */
+		if (I_IGNPAR(driver->tty)) {
+			driver->ignore_status_mask |= LSR_OE | \
+				LSR_PE | LSR_FE;
+			driver->read_status_mask |= LSR_OE | \
+				LSR_PE | LSR_FE;
+		}
+	}
+	driver->comm->data_format = cval;
+	ircomm_append_ctrl(driver->comm, DATA_FORMAT);
+ 	ircomm_append_ctrl(driver->comm, FLOW_CONTROL);
+	ircomm_control_request(driver->comm);
+
+	/* output to IrCOMM here*/
+}
+
+
+
+
+static int irvtd_startup(struct irvtd_cb *driver){
+
+	struct notify_t irvtd_notify;
+
+
+	DEBUG(4,"irvtd_startup:\n" );
+
+	/*
+	 * initialize our tx/rx buffer
+	 */
+
+	if(driver->flags & IRVTD_ASYNC_INITIALIZED)
+		return(0);
+
+	skb_queue_head_init(&driver->rxbuff);
+	driver->rx_tqueue.data = driver;
+	driver->rx_tqueue.routine = irvtd_write_to_tty;
+
+	if(!driver->txbuff){
+		driver->txbuff = dev_alloc_skb(COMM_DEFAULT_DATA_SIZE); 
+		if (!driver->txbuff){
+			DEBUG(0,"irvtd_open():alloc_skb failed!\n");
+			return -ENOMEM;
+		}
+
+		skb_reserve(driver->txbuff, COMM_HEADER_SIZE);
+	}
+
+	irda_notify_init(&irvtd_notify);
+	irvtd_notify.data_indication = irvtd_receive_data;
+	irvtd_notify.connect_confirm = irvtd_connect_confirm;
+	irvtd_notify.connect_indication = irvtd_connect_indication;
+	irvtd_notify.disconnect_indication = irvtd_disconnect_indication;
+	irvtd_notify.flow_indication = irvtd_control_indication;
+	irvtd_notify.instance = driver;
+	strncpy( irvtd_notify.name, "irvtd", NOTIFY_MAX_NAME);
+
+	/*
+	 * register ourself as a service user of IrCOMM
+	 *	   TODO: other servicetype(i.e. 3wire,3wireraw) 
+	 */
+
+	driver->comm = ircomm_attach_cable(NINE_WIRE, irvtd_notify,
+					   irvtd_attached);
+	if(driver->comm == NULL)
+		return -ENODEV;
+	
+	/*
+	 * TODO:we have to initialize control-channel here!
+	 *   i.e.set something into RTS,CTS and so on....
+	 */
+
+	if (driver->tty)
+		clear_bit(TTY_IO_ERROR, &driver->tty->flags);
+
+	change_speed(driver);
+
+	driver->flags |= IRVTD_ASYNC_INITIALIZED;
+	return 0;
+}
+
+
+int irvtd_open(struct tty_struct * tty, struct file * filp){
+	
+	struct irvtd_cb *driver;
+	int retval;
+	int line;
+
+	DEBUG(4, "irvtd_open():\n");
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	if ((line <0) || (line >= COMM_MAX_TTY))
+		return -ENODEV;
+	driver = irvtd[line];
+	driver->line = line;
+	driver->count++;
+
+	DEBUG(0, "irvtd_open : %s%d count %d\n", tty->driver.name, line, 
+	      driver->count);
+	
+	tty->driver_data = driver;
+	driver->tty = tty;
+
+	
+	/* 
+	 * start up discovering process and ircomm_layer 
+	 */
+	
+	retval = irvtd_startup(driver);
+	if (retval)
+		return retval;
+	MOD_INC_USE_COUNT;
+
+	retval = irvtd_block_til_ready(tty, filp, driver);
+	if (retval){
+		DEBUG(0,"irvtd_open returning after block_til_ready with %d\n",
+		      retval);
+                return retval;
+	}
+
+	if ((driver->count == 1) && driver->flags & IRVTD_ASYNC_SPLIT_TERMIOS){
+		if(tty->driver.subtype == IRVTD_TYPE_NORMAL)
+			*tty->termios = driver->normal_termios;
+		else
+			*tty->termios = driver->callout_termios;
+
+ 		change_speed(driver);
+	}
+	
+	driver->session = current->session;
+	driver->pgrp = current->pgrp;
+	driver->rx_disable = 0;
+	return (0);
+}
+
+
+
+
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_close() and friends
+ *
+ * most of this function is stolen from serial.c
+ * ----------------------------------------------------------------------
+ */
+
+
+static void irvtd_shutdown(struct irvtd_cb * driver)
+{
+	unsigned long	flags;
+
+	if (!(driver->flags & IRVTD_ASYNC_INITIALIZED))
+		return;
+
+	DEBUG(4,"irvtd_shutdown:\n");
+
+	/*
+	 * This comment is written in serial.c:
+	 *
+	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
+	 * here so the queue might never be waken up
+	 */
+ 	wake_up_interruptible(&driver->delta_msr_wait);
+	
+	/* clear DTR and RTS */
+	if (!driver->tty || (driver->tty->termios->c_cflag & HUPCL))
+ 		driver->mcr &= ~(MCR_DTR|MCR_RTS);
+
+	driver->comm->dte = driver->mcr;
+	ircomm_append_ctrl(driver->comm, DTELINE_STATE );
+	ircomm_control_request(driver->comm);
+
+
+	save_flags(flags); cli(); /* Disable interrupts */
+
+	if (driver->tty)
+		set_bit(TTY_IO_ERROR, &driver->tty->flags);
+	
+	ircomm_detach_cable(driver->comm);
+
+	/*
+	 * Free the transmit buffer here 
+	 */
+	if(driver->txbuff){
+		dev_kfree_skb(driver->txbuff);     /* is it OK?*/
+		driver->txbuff = NULL;
+	}
+
+	driver->flags &= ~IRVTD_ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+
+
+void irvtd_close(struct tty_struct * tty, struct file * filp){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	int line;
+	unsigned long flags;
+
+	DEBUG(0, "irvtd_close:refc(%d)\n",ircomm_vsd_refcount);
+
+	ASSERT(driver != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+
+	save_flags(flags);cli();
+
+	/* 
+	 * tty_hung_up_p() is defined as 
+	 *   " return(filp->f_op == &hung_up_tty_fops); "
+	 *	 see driver/char/tty_io.c
+	 */
+
+	if(tty_hung_up_p(filp)){
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return;
+	}
+	
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+	DEBUG(0, "irvtd_close : %s%d count %d\n", tty->driver.name, line, 
+	      driver->count);
+
+	if ((tty->count == 1) && (driver->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  Driver->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * ircomm service layer won't be shutdown.
+		 */
+		printk(KERN_ERR"irvtd_close: bad serial port count;" 
+		       "tty->count is 1, but driver->count is %d\n", driver->count);
+		driver->count = 1;
+	}
+	if (--driver->count < 0) {
+		printk("irvtd_close: bad count for line%d: %d\n",
+		       line, driver->count);
+		driver->count = 0;
+	}
+
+	if (driver->count) { 	/* do nothing */
+		MOD_DEC_USE_COUNT;
+		restore_flags(flags);
+		return; 
+	}
+
+	driver->flags |= IRVTD_ASYNC_CLOSING;
+	
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+
+	if (driver->flags & IRVTD_ASYNC_NORMAL_ACTIVE)
+		driver->normal_termios = *tty->termios;
+	if (driver->flags & IRVTD_ASYNC_CALLOUT_ACTIVE)
+		driver->callout_termios = *tty->termios;
+	
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (driver->closing_wait != IRVTD_ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, driver->closing_wait);
+	
+	/* 
+	 * Now we stop accepting input.
+	 */
+
+	driver->rx_disable = TRUE;
+
+	/* 
+	 * Now we flush our buffer.., and shutdown ircomm service layer
+	 */
+
+	/* drop our tx/rx buffer */
+ 	if (tty->driver.flush_buffer) 
+ 		tty->driver.flush_buffer(tty);  
+
+	while(skb_queue_len(&driver->rxbuff)){
+		struct sk_buff *skb;
+		skb = skb_dequeue( &driver->rxbuff);
+		dev_kfree_skb(skb);
+	}
+
+	/* drop users buffer? */
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+
+
+
+	tty->closing = 0;
+	driver->tty = NULL;
+
+	/*
+	 * ad-hoc coding:
+	 * we wait 2 sec before ircomm_detach_cable so that 
+	 * irttp will send all contents of its queue
+	 */
+
+#if 0
+	if (driver->blocked_open) {
+		if (driver->close_delay) {
+#endif
+
+			/* kill time */
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(driver->close_delay + 2*HZ);
+#if 0
+		}
+		wake_up_interruptible(&driver->open_wait);
+	}
+#endif
+	
+	driver->flags &= ~(IRVTD_ASYNC_NORMAL_ACTIVE|
+			   IRVTD_ASYNC_CALLOUT_ACTIVE|
+			   IRVTD_ASYNC_CLOSING);
+        wake_up_interruptible(&driver->close_wait); 
+
+	irvtd_shutdown(driver);
+	MOD_DEC_USE_COUNT;
+        restore_flags(flags);
+	DEBUG(4,"irvtd_close:done:refc(%d)\n",ircomm_vsd_refcount);
+}
+
+
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_write() and friends
+ * This routine will be called when something data are passed from
+ * kernel or user.
+ *
+ * NOTE:I have stolen copy_from_user() from 2.0.30 kernel(linux/isdnif.h)
+ * to access user space of memory carefully. Thanks a lot!:)
+ * ----------------------------------------------------------------------
+ */
+
+int irvtd_write(struct tty_struct * tty, int from_user,
+			const unsigned char *buf, int count){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	int c = 0;
+	int wrote = 0;
+	struct sk_buff *skb = NULL;
+	__u8 *frame;
+
+	DEBUG(4, "irvtd_write():\n");
+
+	if (!tty || !driver->txbuff)
+                return 0;
+
+
+	
+	while(1){
+		skb = driver->txbuff;
+		
+		c = MIN(count, (skb_tailroom(skb) - COMM_HEADER_SIZE));
+		if (c <= 0) 
+			break;
+
+		/* write to the frame */
+
+
+		frame = skb_put(skb,c);
+		if(from_user){
+			copy_from_user(frame,buf,c);
+		} else
+			memcpy(frame, buf, c);
+
+		/* flush the frame */
+		irvtd_flush_chars(tty);
+		wrote += c;
+		count -= c;
+	}
+	return (wrote);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_put_char()
+ * This routine is called by the kernel to pass a single character.
+ * If we exausted our buffer,we can ignore the character!
+ * ----------------------------------------------------------------------
+ */
+void irvtd_put_char(struct tty_struct *tty, unsigned char ch){
+
+	__u8 *frame ;
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	struct sk_buff *skb = driver->txbuff;
+
+	ASSERT(tty->driver_data != NULL, return;);
+
+	DEBUG(4, "irvtd_put_char:\n");
+	if(!driver->txbuff)
+		return;
+
+	DEBUG(4, "irvtd_put_char(0x%02x) skb_len(%d) MAX(%d):\n",
+	      (int)ch ,(int)skb->len,
+	      driver->comm->maxsdusize - COMM_HEADER_SIZE);
+
+	/* append a character  */
+
+	frame = skb_put(skb,1);
+	frame[0] = ch;
+	return;
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_flush_chars() and friend
+ * This routine will be called after a series of characters was written using 
+ * irvtd_put_char().We have to send them down to IrCOMM.
+ * ----------------------------------------------------------------------
+ */
+
+static void flush_txbuff(struct irvtd_cb *driver){
+	
+	struct sk_buff *skb = driver->txbuff;
+	struct tty_struct *tty = driver->tty;
+	ASSERT(tty != NULL, return;);
+
+#ifdef IRVTD_DEBUG_TX
+	printk("flush_txbuff:");
+	{
+		int i;
+		for ( i=0;i<skb->len;i++)
+			printk("%02x", skb->data[i]);
+		printk("\n");
+	}
+#else
+	DEBUG(4, "flush_txbuff:count(%d)\n",(int)skb->len);
+#endif
+
+	/* add "clen" field */
+	skb_push(skb,1);
+	skb->data[0]=0;          /* without control channel */
+
+	ircomm_data_request(driver->comm, driver->txbuff);
+
+	/* allocate new frame */
+	skb = driver->txbuff = dev_alloc_skb(driver->comm->max_txbuff_size);
+	if (skb == NULL){
+		printk(KERN_ERR"flush_txbuff():alloc_skb failed!\n");
+	} else {
+		skb_reserve(skb, COMM_HEADER_SIZE);
+	}
+	wake_up_interruptible(&driver->tty->write_wait);
+}
+
+void irvtd_flush_chars(struct tty_struct *tty){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	if(!driver || driver->magic != IRVTD_MAGIC || !driver->txbuff){
+		DEBUG(0,"irvtd_flush_chars:null structure:ignore\n");
+		return;
+	}
+	DEBUG(4, "irvtd_flush_chars():\n");
+
+	while(tty->hw_stopped){
+		DEBUG(4,"irvtd_flush_chars:hw_stopped:sleep..\n");
+		tty_wait_until_sent(tty,0);
+		DEBUG(4,"irvtd_flush_chars:waken up!\n");
+		if(!driver->txbuff->len)
+			return;
+	}
+
+	flush_txbuff(driver);
+}
+
+
+
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_write_room()
+ * This routine returns the room that our buffer has now.
+ *
+ * NOTE: 
+ * driver/char/n_tty.c drops a character(s) when this routine returns 0,
+ * and then linux will be frozen after a few minutes :(    why? bug?
+ * ( I found this on linux-2.0.33 )
+ * So this routine flushes a buffer if there is few room,     TH
+ * ----------------------------------------------------------------------
+ */
+
+int irvtd_write_room(struct tty_struct *tty){
+
+	int ret;
+	struct sk_buff *skb = (struct sk_buff *)((struct irvtd_cb *) tty->driver_data)->txbuff;
+
+	if(!skb){
+		DEBUG(0,"irvtd_write_room:NULL skb\n");
+		return(0);
+	}
+
+	ret = skb_tailroom(skb) - COMM_HEADER_SIZE;
+
+	if(ret < 0){
+		DEBUG(0,"irvtd_write_room:error:room is %d!",ret);
+		ret = 0;
+	}
+	DEBUG(4, "irvtd_write_room:\n");
+	DEBUG(4, "retval(%d)\n",ret);
+
+
+	/* flush buffer automatically to avoid kernel freeze :< */
+	if(ret < 8)    /* why 8? there's no reason :) */
+		irvtd_flush_chars(tty);
+
+	return(ret);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_chars_in_buffer()
+ * This function returns how many characters which have not been sent yet 
+ * are still in buffer.
+ * ----------------------------------------------------------------------
+ */
+
+int irvtd_chars_in_buffer(struct tty_struct *tty){
+
+	struct sk_buff *skb = 
+		(struct sk_buff *) ((struct irvtd_cb *)tty->driver_data) ->txbuff;
+	DEBUG(4, "irvtd_chars_in_buffer()\n");
+
+	if(!skb){
+		printk(KERN_ERR"irvtd_chars_in_buffer:NULL skb\n");
+		return(0);
+	}
+	return (skb->len );
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_break()
+ * routine which turns the break handling on or off
+ * ----------------------------------------------------------------------
+ */
+
+static void irvtd_break(struct tty_struct *tty, int break_state){
+	
+ 	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	unsigned long flags;
+
+	DEBUG(0, __FUNCTION__"()\n");
+	ASSERT(tty->driver_data != NULL, return;);
+	ASSERT(driver->magic == IRVTD_MAGIC, return;);
+	
+	save_flags(flags);cli();
+	if (break_state == -1)
+	{
+		driver->comm->break_signal = 0x01;
+		ircomm_append_ctrl(driver->comm, BREAK_SIGNAL);
+		ircomm_control_request(driver->comm);
+	}
+	else
+	{
+		driver->comm->break_signal = 0x00;
+		ircomm_append_ctrl(driver->comm, BREAK_SIGNAL);
+		ircomm_control_request(driver->comm);
+	}
+
+	restore_flags(flags);
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_ioctl() and friends
+ * This routine allows us to implement device-specific ioctl's.
+ * If passed ioctl number (i.e.cmd) is unknown one, we should return 
+ * ENOIOCTLCMD.
+ *
+ * TODO: we can't use setserial on IrCOMM because some ioctls are not implemented.
+ * we should add some ioctls and make some tool which is resemble to setserial.
+ * ----------------------------------------------------------------------
+ */
+
+static int get_modem_info(struct irvtd_cb * driver, unsigned int *value)
+{
+	unsigned int result;
+	result =  ((driver->mcr & MCR_RTS) ? TIOCM_RTS : 0)
+		| ((driver->mcr & MCR_DTR) ? TIOCM_DTR : 0)
+		| ((driver->msr & DELTA_DCD) ? TIOCM_CAR : 0)
+		| ((driver->msr & DELTA_RI) ? TIOCM_RNG : 0)
+		| ((driver->msr & DELTA_DSR) ? TIOCM_DSR : 0)
+		| ((driver->msr & DELTA_CTS) ? TIOCM_CTS : 0);
+	put_user(result,value);
+	return 0;
+}
+
+static int set_modem_info(struct irvtd_cb * driver, unsigned int cmd,
+			  unsigned int *value)
+{ 
+	int error;
+	unsigned int arg;
+
+	error = get_user(arg, value);
+	if(error)
+		return error;
+
+	switch (cmd) {
+	case TIOCMBIS: 
+		if (arg & TIOCM_RTS) 
+			driver->mcr |= MCR_RTS;
+		if (arg & TIOCM_DTR)
+			driver->mcr |= MCR_DTR;
+		break;
+		
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS)
+			driver->mcr &= ~MCR_RTS;
+		if (arg & TIOCM_DTR)
+ 			driver->mcr &= ~MCR_DTR;
+ 		break;
+		
+	case TIOCMSET:
+ 		driver->mcr = ((driver->mcr & ~(MCR_RTS | MCR_DTR))
+			       | ((arg & TIOCM_RTS) ? MCR_RTS : 0)
+			       | ((arg & TIOCM_DTR) ? MCR_DTR : 0));
+		break;
+		
+	default:
+		return -EINVAL;
+	}
+	
+	driver->comm->dte = driver->mcr;
+	ircomm_append_ctrl(driver->comm, DTELINE_STATE );
+	ircomm_control_request(driver->comm);
+	return 0;
+}
+
+int irvtd_ioctl(struct tty_struct *tty, struct file * file,
+		unsigned int cmd, unsigned long arg){
+
+	int error;
+ 	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+
+	struct icounter_struct cnow;
+	struct icounter_struct *p_cuser;	/* user space */
+
+
+	DEBUG(4,"irvtd_ioctl:requested ioctl(0x%08x)\n",cmd);
+
+#ifdef IRVTD_DEBUG_IOCTL
+	{
+		/* kill time so that debug messages will come slowly  */
+		unsigned long flags;
+		save_flags(flags);cli();
+		current->state = TASK_INTERRUPTIBLE;
+		current->timeout = jiffies + HZ/4; /*0.25sec*/
+		schedule();
+		restore_flags(flags);
+	}
+#endif
+
+
+
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
+	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR)){
+			DEBUG(0,"irvtd_ioctl:I/O error...\n");
+			return -EIO;
+		}
+	}
+	
+	switch (cmd) {
+
+	case TIOCMGET:
+		error = verify_area(VERIFY_WRITE, (void *) arg,
+				    sizeof(unsigned int));
+		if (error)
+			return error;
+		return get_modem_info(driver, (unsigned int *) arg);
+
+	case TIOCMBIS:
+	case TIOCMBIC:
+	case TIOCMSET:
+		return set_modem_info(driver, cmd, (unsigned int *) arg);
+#if 0
+	/*
+	 * we wouldn't implement them since we don't use serial_struct
+	 */
+	case TIOCGSERIAL:
+		error = verify_area(VERIFY_WRITE, (void *) arg,
+				    sizeof(struct serial_struct));
+		if (error)
+			return error;
+		return irvtd_get_serial_info(driver,
+				       (struct serial_struct *) arg);
+	case TIOCSSERIAL:
+		error = verify_area(VERIFY_READ, (void *) arg,
+				    sizeof(struct serial_struct));
+		if (error)
+			return error;
+		return irvtd_set_serial_info(driver,
+				       (struct serial_struct *) arg);
+
+
+	case TIOCSERGETLSR: /* Get line status register */
+		error = verify_area(VERIFY_WRITE, (void *) arg,
+				    sizeof(unsigned int));
+		if (error)
+			return error;
+		else
+			return get_lsr_info(driver, (unsigned int *) arg);
+#endif		
+
+/*
+ *  I think we don't need them
+ */
+/* 	case TIOCSERCONFIG: */
+		
+
+/*
+ * They cannot be implemented because we don't use async_struct 
+ * which is defined in serial.h
+ */
+
+/* 	case TIOCSERGSTRUCT: */
+/* 		error = verify_area(VERIFY_WRITE, (void *) arg, */
+/* 				    sizeof(struct async_struct)); */
+/* 		if (error) */
+/* 			return error; */
+/* 		memcpy_tofs((struct async_struct *) arg, */
+/* 			    driver, sizeof(struct async_struct)); */
+/* 		return 0; */
+		
+/* 	case TIOCSERGETMULTI: */
+/* 		error = verify_area(VERIFY_WRITE, (void *) arg, */
+/* 				    sizeof(struct serial_multiport_struct)); */
+/* 		if (error) */
+/* 			return error; */
+/* 		return get_multiport_struct(driver, */
+/* 					    (struct serial_multiport_struct *) arg); */
+/* 	case TIOCSERSETMULTI: */
+/* 		error = verify_area(VERIFY_READ, (void *) arg, */
+/* 				    sizeof(struct serial_multiport_struct)); */
+/* 		if (error) */
+/* 			return error; */
+/* 		return set_multiport_struct(driver, */
+/* 					    (struct serial_multiport_struct *) arg); */
+		/*
+		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)
+		 * to change
+		 * - mask passed in arg for lines of interest
+ 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
+		 * Caller should use TIOCGICOUNT to see which one it was
+		 */
+
+	case TIOCMIWAIT:
+		while (1) {
+			interruptible_sleep_on(&driver->delta_msr_wait);
+			/* see if a signal did it */
+/* 			if (current->signal & ~current->blocked) */
+/* 				return -ERESTARTSYS; */
+
+			if ( ((arg & TIOCM_RNG) && (driver->msr & DELTA_RI))  ||
+			     ((arg & TIOCM_DSR) && (driver->msr & DELTA_DSR)) ||
+			     ((arg & TIOCM_CD)  && (driver->msr & DELTA_DCD)) ||
+			     ((arg & TIOCM_CTS) && (driver->msr & DELTA_CTS))) {
+				return 0;
+			}
+		}
+		/* NOTREACHED */
+
+
+	case TIOCGICOUNT:
+		/* 
+		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
+		 * Return: write counters to the user passed counter struct
+		 * NB: both 1->0 and 0->1 transitions are counted except for
+		 *     RI where only 0->1 is counted.
+		 */
+		error = verify_area(VERIFY_WRITE, (void *) arg,
+				    sizeof(struct icounter_struct));
+		if (error)
+			return error;
+		cli();
+		cnow = driver->icount;
+		sti();
+		p_cuser = (struct icounter_struct *) arg;
+		put_user(cnow.cts, &p_cuser->cts);
+		put_user(cnow.dsr, &p_cuser->dsr);
+		put_user(cnow.rng, &p_cuser->rng);
+		put_user(cnow.dcd, &p_cuser->dcd);
+		return 0;
+
+
+	case TIOCGSERIAL:
+	case TIOCSSERIAL:
+	case TIOCSERGETLSR:
+ 	case TIOCSERCONFIG:
+	case TIOCSERGWILD:
+	case TIOCSERSWILD:
+	case TIOCSERGSTRUCT:
+	case TIOCSERGETMULTI:
+	case TIOCSERSETMULTI:
+		DEBUG(0,"irvtd_ioctl:sorry, ioctl(0x%08x)is not implemented\n",cmd);
+		return -ENOIOCTLCMD;  /* ioctls which are imcompatible with serial.c */
+
+	case TCSETS:
+	case TCGETS:
+	case TCFLSH:
+	default:
+		return -ENOIOCTLCMD;  /* ioctls which we must not touch */
+	}
+	return 0;
+}
+
+
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_set_termios()
+ * This is called when termios is changed.
+ * If things that changed is significant for us,(i.e. changing baud rate etc.)
+ * send something to peer device.
+ * ----------------------------------------------------------------------
+ */
+
+void irvtd_set_termios(struct tty_struct *tty, struct termios * old_termios){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+
+	ASSERT(driver != NULL,return;);
+	ASSERT(driver->magic == IRVTD_MAGIC ,return;);
+
+	DEBUG(0, "irvtd_set_termios:\n");
+	return;
+
+	if((tty->termios->c_cflag == old_termios->c_cflag) &&
+	   (RELEVANT_IFLAG(tty->termios->c_iflag) 
+	    == RELEVANT_IFLAG(old_termios->c_iflag)))
+		return;
+
+	change_speed(driver);
+
+	if((old_termios->c_cflag & CRTSCTS) &&
+	   !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = driver->ttp_stoptx;
+		/* irvtd_start(tty); */       /* we don't need this */
+	}
+}
+
+/*
+ * ----------------------------------------------------------------------
+ * irvtd_throttle,irvtd_unthrottle
+ *   These routines will be called when we have to pause sending up data to tty.
+ *   We use RTS virtual signal when servicetype is NINE_WIRE
+ * ----------------------------------------------------------------------
+ */
+
+static void irvtd_send_xchar(struct tty_struct *tty, char ch){
+
+	DEBUG(0, __FUNCTION__"():\n");
+	irvtd_put_char(tty, ch);
+}
+
+void irvtd_throttle(struct tty_struct *tty){
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+
+	DEBUG(0, "irvtd_throttle:\n");
+
+	if (I_IXOFF(tty))
+		irvtd_put_char(tty, STOP_CHAR(tty));
+
+	driver->mcr &= ~MCR_RTS; 
+	driver->mcr |= DELTA_RTS; 
+	driver->comm->dte = driver->mcr;
+	ircomm_append_ctrl(driver->comm, DTELINE_STATE );
+	ircomm_control_request(driver->comm);
+        irttp_flow_request(driver->comm->tsap, FLOW_STOP);
+}
+
+void irvtd_unthrottle(struct tty_struct *tty){
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	DEBUG(0, "irvtd_unthrottle:\n");
+
+	if (I_IXOFF(tty))
+		irvtd_put_char(tty, START_CHAR(tty));
+
+	driver->mcr |= (MCR_RTS|DELTA_RTS);
+	driver->comm->dte = driver->mcr;
+	ircomm_append_ctrl(driver->comm, DTELINE_STATE );
+	ircomm_control_request(driver->comm);
+        irttp_flow_request(driver->comm->tsap, FLOW_START);
+}
+
+
+/*
+ * ------------------------------------------------------------
+ * irvtd_stop() and irvtd_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable an interrupt which means "transmitter-is-ready"
+ * in serial.c, but  I think these routine are not necessary for us. 
+ * ------------------------------------------------------------
+ */
+
+#if 0
+irvtd_stop(struct tty_struct *tty){
+ 	DEBUG(0, "irvtd_stop()\n");
+
+	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data; 
+	DEBUG(0, "irvtd_start():not implemented!\n");
+}
+irvtd_start(struct tty_struct *tty){
+
+	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data;
+	DEBUG(0, "irvtd_start():not_implemented!\n");
+}
+#endif
+
+/*
+ * ------------------------------------------------------------
+ * irvtd_hangup()
+ * This routine notifies that tty layer have got HUP signal
+ * Is this routine right ? :{|
+ * ------------------------------------------------------------
+ */
+
+void irvtd_hangup(struct tty_struct *tty){
+
+	struct irvtd_cb *info = (struct irvtd_cb *)tty->driver_data;
+	DEBUG(0, "irvtd_hangup()\n");
+
+	irvtd_flush_buffer(tty);
+	irvtd_shutdown(info);
+	info->count = 0;
+	info->flags &= ~(IRVTD_ASYNC_NORMAL_ACTIVE|IRVTD_ASYNC_CALLOUT_ACTIVE);
+	info->tty = NULL;
+	wake_up_interruptible(&info->open_wait);
+}
+
+void irvtd_flush_buffer(struct tty_struct *tty){
+
+	struct irvtd_cb *driver = (struct irvtd_cb *)tty->driver_data;
+	struct sk_buff *skb;
+
+	skb = (struct sk_buff *)driver->txbuff;
+
+	DEBUG(4, "irvtd_flush_buffer:%d chars are gone..\n",(int)skb->len);
+	skb_trim(skb,0); 
+	
+	/* write_wait is a wait queue of tty_wait_until_sent().
+	 * see tty_io.c of kernel 
+	 */
+ 	wake_up_interruptible(&tty->write_wait); 
+
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.1.131/linux/net/irda/irda_device.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irda_device.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,578 @@
+/*********************************************************************
+ *                
+ * Filename:      irda_device.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Wed Sep  2 20:22:08 1998
+ * Modified at:   Mon Dec 14 19:18:51 1998
+ * 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/config.h>
+#include <linux/proc_fs.h>
+#include <linux/skbuff.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/init.h>
+
+#include <net/pkt_sched.h>
+#include <asm/dma.h>
+
+#include <net/irda/irda_device.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/timer.h>
+#include <net/irda/wrapper.h>
+
+extern int irtty_init(void);
+extern int pc87108_init(void);
+extern int w83977af_init(void);
+extern int esi_init(void);
+extern int tekram_init(void);
+extern int actisys_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, 
+				       struct device *dev,
+				       unsigned short type, void *daddr, 
+				       void *saddr, unsigned len);
+static int irda_device_net_set_config( struct device *dev, struct ifmap *map);
+static int irda_device_net_change_mtu( struct device *dev, int new_mtu);
+
+#ifdef CONFIG_PROC_FS
+int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
+			   int unused);
+
+#endif /* CONFIG_PROC_FS */
+
+__initfunc(int irda_device_init( void))
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Allocate master array */
+	irda_device = hashbin_new( HB_LOCAL);
+	if ( irda_device == NULL) {
+		printk( KERN_WARNING "IrDA: Can't allocate irda_device hashbin!\n");
+		return -ENOMEM;
+	}
+
+	/* 
+	 * Call the init function of the device drivers that has not been
+	 * compiled as a module 
+	 */
+#ifdef CONFIG_IRTTY_SIR
+	irtty_init();
+#endif
+#ifdef CONFIG_WINBOND_FIR
+	w83977af_init();
+#endif
+#ifdef CONFIG_NSC_FIR
+	pc87108_init();
+#endif
+#ifdef CONFIG_ESI_DONGLE
+	esi_init();
+#endif
+#ifdef CONFIG_TEKRAM_DONGLE
+	tekram_init();
+#endif
+#ifdef CONFIG_ACTISYS_DONGLE
+	actisys_init();
+#endif
+
+	return 0;
+}
+
+void irda_device_cleanup(void)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( irda_device != NULL, return;);
+
+	hashbin_delete( irda_device, (FREE_FUNC) irda_device_close);
+}
+
+/*
+ * Function irda_device_open (self)
+ *
+ *    Open a new IrDA port device
+ *
+ */
+int irda_device_open( struct irda_device *self, char *name, void *priv)
+{        
+	int result;
+	int i=0;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");     
+
+	/* Check that a minimum of allocation flags are specified */
+	ASSERT(( self->rx_buff.flags & (GFP_KERNEL|GFP_ATOMIC)) != 0, 
+	       return -1;);
+	ASSERT(( self->tx_buff.flags & (GFP_KERNEL|GFP_ATOMIC)) != 0, 
+	       return -1;);
+
+	ASSERT( self->tx_buff.truesize > 0, return -1;);
+	ASSERT( self->rx_buff.truesize > 0, return -1;);
+
+	self->rx_buff.data = ( __u8 *) kmalloc( self->rx_buff.truesize, 
+						self->rx_buff.flags);
+	self->tx_buff.data = ( __u8 *) kmalloc( self->tx_buff.truesize, 
+						self->tx_buff.flags);
+
+	if ( self->rx_buff.data == NULL || self->tx_buff.data == NULL)   {
+		DEBUG( 0, "IrDA Self: no space for buffers!\n");
+		irda_device_close( self);
+		return -ENOMEM;
+	}
+
+	memset( self->rx_buff.data, 0, self->rx_buff.truesize);
+	memset( self->tx_buff.data, 0, self->tx_buff.truesize);
+	
+	self->magic = IRDA_DEVICE_MAGIC;
+
+	self->rx_buff.in_frame = FALSE;
+	self->rx_buff.state = OUTSIDE_FRAME;
+
+	/* Initialize timers */
+	init_timer( &self->media_busy_timer);	
+
+	/* Open new IrLAP layer instance */
+	self->irlap = irlap_open( self);
+
+	/* A pointer to the low level implementation */
+	self->priv = priv;
+	strncpy( self->name, name, 16);
+
+	/* Initialize IrDA net device */
+	do {
+		sprintf( self->name, "%s%d", "irda", i++);
+	} while ( dev_get( self->name) != NULL);
+	
+	self->netdev.name = self->name;
+	self->netdev.priv = (void *) self;
+	self->netdev.next = NULL;
+
+	if (( result = register_netdev( &self->netdev)) != 0) {
+		DEBUG( 0, "IrDA Device, register_netdev() failed!\n");
+		return -1;
+	}
+
+	hashbin_insert( irda_device, (QUEUE *) self, (int) self, NULL);
+
+	/* Open network device */
+	dev_open( &self->netdev);
+
+	printk( "IrDA irda_device %s registered.\n", self->name);
+
+	irda_device_set_media_busy( self, FALSE);
+        
+	return 0;
+}
+
+/*
+ * Function irda_device_close (self)
+ *
+ *    Close this instance of the irda_device, just deallocate buffers
+ *
+ */
+void __irda_device_close( struct irda_device *self)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+
+	dev_close( &self->netdev);
+
+	/* Remove netdevice */
+	unregister_netdev( &self->netdev);
+
+	/* Stop timers */
+	del_timer( &self->todo_timer);
+	del_timer( &self->media_busy_timer);
+
+	if ( self->tx_buff.data) {
+		kfree( self->tx_buff.data);
+	}
+
+	if ( self->rx_buff.data) {
+		kfree( self->rx_buff.data);
+	}
+
+	self->magic = 0;
+}
+
+/*
+ * Function irda_device_close (self)
+ *
+ *    
+ *
+ */
+void irda_device_close( struct irda_device *self)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+
+	/* Stop IrLAP */
+	irlap_close( self->irlap);
+	self->irlap = NULL;
+
+	hashbin_remove( irda_device, (int) self, NULL);
+
+	__irda_device_close( self);
+}
+
+/*
+ * Function irda_device_set_media_busy (self, status)
+ *
+ *    Called when we have detected that another station is transmiting
+ *    in contention mode.
+ */
+void irda_device_set_media_busy( struct irda_device *self, int status) 
+{
+	DEBUG( 4, __FUNCTION__ "(%s)\n", status ? "TRUE" : "FALSE");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+
+	if ( status) {
+		self->media_busy = TRUE;
+		irda_device_start_mbusy_timer( self);
+		DEBUG( 4, "Media busy!\n");
+	} else {
+		self->media_busy = FALSE;
+		del_timer( &self->media_busy_timer);
+	}
+}
+
+/*
+ * Function __irda_device_change_speed (self, speed)
+ *
+ *    When this function is called, we will have a process context so its
+ *    possible for us to sleep, wait or whatever :-)
+ */
+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;
+	}
+
+	/*
+	 *  Is is possible to change speed yet? Wait until the last byte 
+	 *  has been transmitted.
+	 */
+	if ( self->wait_until_sent) {
+		self->wait_until_sent( self);
+		
+		if ( self->change_speed) {
+			self->change_speed( self, speed);
+			
+			/* Update the QoS value only */
+			self->qos.baud_rate.value = speed;
+		}
+	} else {
+		DEBUG( 0, __FUNCTION__ "(), Warning, wait_until_sent() "
+		       "is not implemented by the irda_device!\n");
+     
+	}
+}
+
+/*
+ * Function irda_device_change_speed (self, speed)
+ *
+ *    Change the speed of the currently used irda_device
+ *
+ */
+inline void irda_device_change_speed( struct irda_device *self, int speed)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+
+	irda_execute_as_process( self, 
+				 (TODO_CALLBACK) __irda_device_change_speed, 
+				 speed);
+}
+
+inline int irda_device_is_media_busy( struct irda_device *self)
+{
+	ASSERT( self != NULL, return FALSE;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+	
+	return self->media_busy;
+}
+
+inline int irda_device_is_receiving( struct irda_device *self)
+{
+	ASSERT( self != NULL, return FALSE;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+	if ( self->is_receiving)
+		return self->is_receiving( self);
+	else
+		return FALSE;
+}
+
+inline struct qos_info *irda_device_get_qos( struct irda_device *self)
+{
+	ASSERT( self != NULL, return NULL;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return NULL;);
+
+	return &self->qos;
+}
+
+void irda_device_todo_expired( unsigned long data)
+{
+	struct irda_device *self = ( struct irda_device *) data;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	/* Check that we still exist */
+	if ( !self || self->magic != IRDA_DEVICE_MAGIC) {
+		return;
+	}
+	__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;
+
+	return &priv->stats;
+}
+
+/*
+ * Function irda_device_setup (dev)
+ *
+ *    This function should be used by low level device drivers in a similar way
+ *    as ether_setup() is used by normal network device drivers
+ */
+int irda_device_setup( struct device *dev) 
+{
+	struct irda_device *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( dev != NULL, return -1;);
+
+	self = (struct irda_device *) dev->priv;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return -1;);	
+
+	dev->get_stats	     = irda_device_get_stats;
+	dev->rebuild_header  = irda_device_net_rebuild_header;
+	dev->set_config      = irda_device_net_set_config;
+	dev->change_mtu      = irda_device_net_change_mtu;
+	dev->hard_header     = irda_device_net_hard_header;
+        dev->hard_header_len = 0;
+        dev->addr_len        = 0;
+
+        dev->type            = ARPHRD_IRDA;
+        dev->tx_queue_len    = 10;  /* Short queues in IrDA */
+ 
+	memcpy( dev->dev_addr, &self->irlap->saddr, 4);
+	memset( dev->broadcast, 0xff, 4);
+
+	dev->mtu = 2048;
+	dev->tbusy = 1;
+	
+	dev_init_buffers( dev);
+
+	dev->flags = 0; /* IFF_NOARP | IFF_POINTOPOINT; */
+	
+	return 0;
+}
+
+/*
+ * Function irda_device_net_rebuild_header (buff, dev, dst, skb)
+ *
+ *    
+ *
+ */
+static int irda_device_net_rebuild_header( struct sk_buff *skb)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	return 0;
+}
+
+static int irda_device_net_hard_header (struct sk_buff *skb, 
+					struct device *dev,
+					unsigned short type, void *daddr, 
+					void *saddr, unsigned len)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	skb->mac.raw = skb->data;
+        /* skb_push(skb,PPP_HARD_HDR_LEN); */
+/*         return PPP_HARD_HDR_LEN; */
+	
+	return 0;
+}
+
+static int irda_device_net_set_config( struct device *dev, struct ifmap *map)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	return 0;
+}
+
+static int irda_device_net_change_mtu( struct device *dev, int new_mtu)
+{
+     DEBUG( 0, __FUNCTION__ "()\n");
+     
+     return 0;  
+}
+
+/*
+ * Function irda_device_transmit_finished (void)
+ *
+ *    Check if there is still some frames in the transmit queue for this
+ *    device
+ *
+ */
+int irda_device_txqueue_empty( struct irda_device *self)
+{
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return -1;);	
+
+	/* FIXME: check if this is the right way of doing it? */
+	if ( skb_queue_len( &self->netdev.qdisc->q))
+		return FALSE;
+
+	return TRUE;
+}
+
+/*
+ * Function irda_get_mtt (skb)
+ *
+ *    Utility function for getting the 
+ *
+ */
+__inline__ int irda_get_mtt( struct sk_buff *skb)
+{
+        return ((struct irlap_skb_cb *)(skb->cb))->mtt;
+}
+
+/*
+ * Function setup_dma (idev, buffer, count, mode)
+ *
+ *    Setup the DMA channel
+ *
+ */
+void setup_dma( int channel, char *buffer, int count, int mode)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+
+	disable_dma( channel);
+	clear_dma_ff( channel);
+	set_dma_mode( channel, mode);
+	set_dma_addr( channel, virt_to_bus(buffer));
+	set_dma_count( channel, count);
+	enable_dma( channel);
+
+	restore_flags(flags);
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irlap_proc_read (buf, start, offset, len, unused)
+ *
+ *    Give some info to the /proc file system
+ *
+ */
+int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
+		      int unused)
+{
+	struct irda_device *self;
+	unsigned long flags;
+     
+	save_flags(flags);
+	cli();
+
+	len = 0;
+
+	self = (struct irda_device *) hashbin_get_first( irda_device);
+	while ( self != NULL) {
+		len += sprintf( buf+len, "Irda_Device name: %s\n", self->name);
+		len += sprintf( buf+len, "  bps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\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);
+	}
+	restore_flags(flags);
+
+	return len;
+}
+
+#endif /* CONFIG_PROC_FS */
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.1.131/linux/net/irda/iriap.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/iriap.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,922 @@
+/*********************************************************************
+ *                
+ * Filename:      iriap.c
+ * Version:       0.1
+ * 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:   Wed Dec  9 02:19:23 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/config.h>
+#include <asm/byteorder.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/string.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_event.h>
+#include <net/irda/iriap.h>
+
+hashbin_t *iriap = NULL;
+
+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);
+
+/*
+ * Function iriap_init (void)
+ *
+ *    Initializes the IrIAP layer, called by the module initialization code
+ *    in irmod.c 
+ */
+int iriap_init(void) 
+{
+	struct ias_object *obj;
+
+	DEBUG( 4, "--> iriap_init\n");
+	
+	/* Allocate master array */
+	iriap = hashbin_new( HB_LOCAL);
+	if ( iriap == NULL) {
+		printk( KERN_WARNING "IrIAP: Can't allocate iriap hashbin!\n");
+		return -ENOMEM;
+	}
+
+	objects = hashbin_new( HB_LOCAL);
+	if ( objects == NULL) {
+		printk( KERN_WARNING 
+			"IrIAP: Can't allocate objects hashbin!\n");
+		return -ENOMEM;
+	}
+
+	/* 
+	 *  Register some default services for IrLMP 
+	 */
+	irlmp_register_layer( S_COMPUTER, SERVER | CLIENT, FALSE, NULL);
+	irlmp_register_layer( S_PNP, SERVER, FALSE, NULL);
+
+	/* 
+	 *  Register the Device object with LM-IAS
+	 */
+	obj = irias_new_object( "Device", IAS_DEVICE_ID);
+	irias_add_string_attrib( obj, "DeviceName", "Linux");
+	irias_insert_object( obj);
+
+	/*  
+	 *  Register server support with IrLMP so we can accept incoming 
+	 *  connections 
+	 */
+	iriap_open( LSAP_IAS, IAS_SERVER);
+	
+	DEBUG( 4, "iriap_init -->\n");
+	
+	return 0;
+}
+
+/*
+ * Function iriap_cleanup (void)
+ *
+ *    Initializes the IrIAP layer, called by the module cleanup code in 
+ *    irmod.c
+ */
+void iriap_cleanup(void) 
+{
+	DEBUG( 4, "--> iriap_cleanup\n");
+
+	irlmp_unregister_layer( S_COMPUTER, SERVER | CLIENT);
+	irlmp_unregister_layer( S_PNP, SERVER);
+	
+	hashbin_delete( iriap, (FREE_FUNC) __iriap_close);
+	hashbin_delete( objects, (FREE_FUNC) __irias_delete_object);
+	
+	DEBUG( 4, "iriap_cleanup -->\n");
+}
+
+/*
+ * Function iriap_open (void)
+ *
+ *    Opens an instance of the IrIAP layer, and registers with IrLMP
+ */
+struct iriap_cb *iriap_open( __u8 slsap_sel, int mode)
+{
+	struct iriap_cb *self;
+	struct notify_t notify;
+	struct lsap_cb *lsap;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	self = kmalloc( sizeof(struct iriap_cb), GFP_ATOMIC);
+	if ( self == NULL) {
+		DEBUG( 0, "iriap_open(), Unable to kmalloc!\n");
+		return NULL;
+	}
+
+	/*
+	 *  Initialize instance
+	 */
+	memset( self, 0, sizeof(struct iriap_cb));
+
+	irda_notify_init( &notify);
+	notify.connect_confirm = iriap_connect_confirm;
+	notify.connect_indication = iriap_connect_indication;
+	notify.disconnect_indication = iriap_disconnect_indication;
+	notify.data_indication = iriap_data_indication;
+	notify.instance = self;
+	if ( mode == IAS_CLIENT)
+		strcpy( notify.name, "IrIAS cli");
+	else
+		strcpy( notify.name, "IrIAS srv");
+
+	lsap = irlmp_open_lsap( slsap_sel, &notify);
+	if ( lsap == NULL) {
+		DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
+		return NULL;
+	}
+	DEBUG( 4, "iriap_register: 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);
+
+	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
+	
+	iriap_next_client_state( self, S_DISCONNECT);
+	iriap_next_call_state( self, S_MAKE_CALL);
+	iriap_next_server_state( self, R_DISCONNECT);
+	iriap_next_r_connect_state( self, R_WAITING);
+	
+	return self;
+}
+
+/*
+ * Function __iriap_close (self)
+ *
+ *    Removes (deallocates) the IrIAP instance
+ *
+ */
+static void __iriap_close( struct iriap_cb *self)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	del_timer( &self->watchdog_timer);
+
+	self->magic = 0;
+
+	kfree( self);
+}
+
+/*
+ * Function iriap_close (void)
+ *
+ *    Closes IrIAP and deregisters with IrLMP
+ */
+void iriap_close( struct iriap_cb *self)
+{
+	DEBUG( 4, "iriap_close()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	if ( self->lsap) {
+		irlmp_close_lsap( self->lsap);
+		self->lsap = NULL;
+	}
+
+	hashbin_remove( iriap, self->slsap_sel, NULL);
+
+	__iriap_close( self);
+}
+
+/*
+ * Function iriap_disconnect_indication (handle, reason)
+ *
+ *    Got disconnect, so clean up everything assosiated with this connection
+ *
+ */
+void iriap_disconnect_indication( void *instance, void *sap, LM_REASON reason, 
+				  struct sk_buff *userdata)
+{
+	struct iriap_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	self = (struct iriap_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	ASSERT( iriap != NULL, return;);
+
+	del_timer( &self->watchdog_timer);
+
+	if ( self->mode == IAS_CLIENT) {
+		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
+
+		/* Inform service user */
+		if ( self->confirm)
+			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, 
+				       NULL);
+	}
+
+	if ( userdata) {
+		dev_kfree_skb( userdata);
+	}
+}
+
+/*
+ * Function iriap_disconnect_request (handle)
+ *
+ *    
+ *
+ */
+void iriap_disconnect_request( struct iriap_cb *self)
+{
+	struct sk_buff *skb;
+
+	DEBUG( 4, "iriap_disconnect_request()\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);
+		return;
+	}
+
+	/* 
+	 *  Reserve space for MUX and LAP header 
+	 */
+ 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+
+	irlmp_disconnect_request( self->lsap, skb);
+}
+
+void iriap_getinfobasedetails_request(void) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+}
+
+void iriap_getinfobasedetails_confirm(void) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+}
+
+void iriap_getobjects_request(void) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+}
+
+void iriap_getobjects_confirm(void) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+}
+
+void iriap_getvalue(void) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+}
+
+/*
+ * Function iriap_getvaluebyclass (addr, name, attr)
+ *
+ *    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)
+{
+	struct sk_buff *skb;
+	struct iriap_cb *self;
+	__u8 *frame;
+	int name_len, attr_len;
+	__u8 slsap = LSAP_ANY;  /* Source LSAP to use */
+
+	DEBUG( 4, "iriap_getvaluebyclass_request()\n");
+	
+	self = iriap_open( slsap, IAS_CLIENT);
+	if ( self == NULL)
+		return;
+
+	self->mode = IAS_CLIENT;
+	self->confirm = callback;
+	self->priv = priv;
+	self->daddr = daddr;
+
+	/* 
+	 *  Save operation, so we know what the later indication is about
+	 */
+	self->operation = GET_VALUE_BY_CLASS; 
+
+	/* Give ourselves 7 secs to finish this operation */
+	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);
+		return;
+	}
+
+	name_len = strlen( name);
+	attr_len = strlen( attr);
+
+	/* Reserve space for MUX and LAP header */
+ 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+	skb_put( skb, 3+name_len+attr_len);
+	frame = skb->data;
+
+	/* Build frame */
+	frame[0] = LST | GET_VALUE_BY_CLASS;
+	frame[1] = name_len;                       /* Insert length of name */
+	memcpy( frame+2, name, name_len);          /* Insert name */
+	frame[2+name_len] = attr_len;              /* Insert length of attr */
+	memcpy( frame+3+name_len, attr, attr_len); /* Insert attr */
+
+	iriap_do_client_event( self, IAP_CALL_REQUEST_GVBC, skb);
+}
+
+/*
+ * Function iriap_getvaluebyclass_confirm (self, skb)
+ *
+ *    Got result from GetValueByClass command. Parse it and return result
+ *    to service user.
+ *
+ */
+void iriap_getvaluebyclass_confirm( struct iriap_cb *self, 
+				    struct sk_buff *skb) 
+{
+	struct ias_value *value;
+	__u16 obj_id;
+	int   len;
+	__u8  type;
+	int   value_len;
+	__u8 *fp;
+	int n;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	/* Initialize variables */
+	fp = skb->data;
+	n = 2;
+
+	/* Get length, MSB first */
+	len = ntohs( *(__u16 *)( fp+n)); n += 2;
+
+	DEBUG( 4, "iriap_getvaluebyclass_confirm: len=%d\n", len);
+
+	/* Get object ID, MSB first */
+	obj_id = ntohs( *(__u16 *)( fp+n)); n += 2;
+
+	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); 
+		break;
+	case IAS_STRING:
+		/* FIXME: check len of string, and if string is/should be
+		 *  null terminated? */
+		ASSERT( fp[n++] == 0, return;); /* ASCII only! */
+		value_len = fp[n++];
+		DEBUG( 0, __FUNCTION__ "(), strlen=%d\n", value_len);
+		ASSERT( value_len < 64, return;);
+		
+		DEBUG( 0, "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);
+		ASSERT(value_len <= 55, return;);      
+		
+		value = irias_new_octseq_value( fp+n, value_len);
+		
+		break;
+	default:
+		value = &missing;
+		break;
+	}
+	
+	if ( self->confirm)
+		self->confirm(obj_id, value, self->priv);
+	
+	/*
+	 * Finished, close connection!
+	 */
+	iriap_disconnect_request( self);
+}
+
+/*
+ * Function iriap_getvaluebyclass_response ()
+ *
+ *    Send answer to getvaluebyclass_indication back to peer LM-IAS
+ * 
+ */
+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");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	/* Initialize variables */
+	n = 0;
+
+	/* 
+	 *  FIXME: adjust the size of the response after the length of the 
+	 *  value 
+	 */
+	skb = dev_alloc_skb( 64);
+	if (skb == NULL) {
+		DEBUG( 0, __FUNCTION__ "(),"
+		       "Could not allocate an skb of length %d\n", 64);
+		return;
+	}
+
+	/* Reserve space for MUX and LAP header */
+ 	skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+	skb_put( skb, 6);
+	
+	fp = skb->data;
+
+	/* Build frame */
+	fp[n++] = GET_VALUE_BY_CLASS | LST;
+	fp[n++] = ret_code;
+
+	/* Insert list length (MSB first) */
+	*((__u16 *) (fp+n)) = __constant_htons( 0x0001); n += 2; 
+
+	/* Insert object identifier ( MSB first) */
+	*((__u16 *) (fp+n)) = htons( obj_id); n += 2;
+
+	switch( value->type) {
+	case IAS_STRING:
+		skb_put( skb, 3 + value->len);
+		fp[n++] = value->type;
+		fp[n++] = 0; /* ASCII */
+		fp[n++] = (__u8) value->len;
+		memcpy( fp+n, value->t.string, value->len); n+=value->len;
+		break;
+	case IAS_INTEGER:
+		skb_put( skb, 5);
+		fp[n++] = value->type;
+		
+		*((__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;
+		memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
+		
+		break;
+	case IAS_MISSING:
+		DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
+		skb_put( skb, 1);
+		fp[n++] = value->type;
+		break;
+
+	default:
+		DEBUG( 0, "iriap_getvaluebyclass_response: "
+		       "type not implemented!\n");
+		break;
+	}
+	iriap_do_r_connect_event( self, IAP_CALL_RESPONSE, skb);
+}
+
+/*
+ * Function iriap_getvaluebyclass_indication (self, skb)
+ *
+ *    getvaluebyclass is requested from peer LM-IAS
+ *
+ */
+void iriap_getvaluebyclass_indication( struct iriap_cb *self,
+				       struct sk_buff *skb)
+{
+	__u8 *fp;
+	int n;
+	int name_len;
+	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");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	fp = skb->data;
+	n = 1;
+
+	name_len = fp[n++];
+	memcpy( name, fp+n, name_len); n+=name_len;
+	name[name_len] = '\0';
+
+	attr_len = fp[n++]; 
+	memcpy( attr, fp+n, attr_len); n+=attr_len;
+	attr[attr_len] = '\0';
+
+	dev_kfree_skb( skb);
+
+	/* 
+	 *  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);
+
+	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);
+	
+	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);
+		return;
+	}
+	
+	DEBUG( 0, "LM-IAS: found %s\n", attrib->name);
+	
+	/*
+	 * We have a match; send the value.
+	 */
+	iriap_getvaluebyclass_response( self, obj->id, IAS_SUCCESS, 
+					attrib->value);
+
+	return;
+}
+
+/*
+ * Function iriap_send_ack (void)
+ *
+ *    
+ *
+ */
+void iriap_send_ack( struct iriap_cb *self) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+
+	DEBUG( 6, "iriap_send_ack()\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);
+		return;
+	}
+
+	/* Reserve space for MUX and LAP header */
+ 	skb_reserve( skb, 4);
+	skb_put( skb, 3);
+	frame = skb->data;
+
+	/* Build frame */
+	frame[0] = LST | self->operation;
+}
+
+/*
+ * Function iriap_connect_confirm (handle, skb)
+ *
+ *    LSAP connection confirmed!
+ *
+ */
+void iriap_connect_confirm( void *instance, void *sap, struct qos_info *qos, 
+			    int max_sdu_size, struct sk_buff *userdata)
+{
+	struct iriap_cb *self;
+	
+	self = ( struct iriap_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( userdata != NULL, return;);
+	
+	DEBUG( 4, "iriap_connect_confirm()\n");
+	
+	del_timer( &self->watchdog_timer);
+
+	iriap_do_client_event( self, IAP_LM_CONNECT_CONFIRM, userdata);
+}
+
+/*
+ * Function iriap_connect_indication ( handle, skb)
+ *
+ *    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)
+{
+	struct iriap_cb *self;
+
+	DEBUG( 4, "iriap_connect_indication()\n");
+
+	self = ( struct iriap_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( self->mode == IAS_SERVER, return;);
+
+	iriap_do_server_event( self, IAP_LM_CONNECT_INDICATION, userdata);
+}
+ 
+/*
+ * Function iriap_data_indication (handle, skb)
+ *
+ *    Receives data from connection identified by handle from IrLMP
+ *
+ */
+void iriap_data_indication( void *instance, void *sap, struct sk_buff *skb) 
+{
+	struct iriap_cb *self;
+	__u8  *frame;
+	__u8  opcode;
+	
+	DEBUG( 4, "iriap_data_indication()\n"); 
+	
+	self = ( struct iriap_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	ASSERT( skb != NULL, return;);
+
+	frame = skb->data;
+	
+	if ( self->mode == IAS_SERVER) {
+		/* Call server */
+		DEBUG( 4, __FUNCTION__ "(), Calling server!\n");
+		iriap_do_r_connect_event( self, IAP_RECV_F_LST, skb);
+
+		return;
+	}
+	opcode = frame[0];
+	if ( ~opcode & 0x80) {
+		printk( KERN_ERR "IrIAS multiframe commands or results is "
+			"not implemented yet!\n");
+		return;
+	}
+
+	if ( ~opcode &0x40) {
+		DEBUG( 4, "Got ack frame!\n");
+	/* 	return; */
+	}
+
+	opcode &= 0x7f; /* Mask away LST bit */
+	
+	switch( opcode) {
+	case GET_INFO_BASE:
+		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		break;
+	case GET_VALUE_BY_CLASS:
+		DEBUG( 4,"IrLMP GetValueByClass\n");
+		
+		if ( frame[1] == 0x01) {
+			printk( KERN_WARNING "IrIAP No such class!\n");
+		} else if ( frame[1] == 0x02) {
+			printk( KERN_WARNING 
+				"IrIAP No such attribute!\n");
+		} else {
+			iriap_getvaluebyclass_confirm( self, skb);
+		}
+		iriap_do_call_event( self, IAP_RECV_F_LST, skb);
+
+		/*  
+		 *  We remove LSAPs used by IrIAS as a client since these
+		 *  are more difficult to reuse!  
+		 */
+		iriap_close( self);
+		break;
+	default:
+		DEBUG( 0, "iriap_data_indication: Unknown op-code: %02x\n", 
+		       opcode);
+		break;
+	}
+}
+
+/*
+ * Function iriap_call_indication (self, skb)
+ *
+ *    Received call to server from peer LM-IAS
+ *
+ */
+void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb)
+{
+	__u8 *fp;
+	__u8  opcode;
+
+	DEBUG( 4, "iriap_call_indication()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	fp = skb->data;
+
+	opcode = fp[0];
+	if ( ~opcode & 0x80) {
+		printk( KERN_ERR "IrIAS multiframe commands or results is "
+			"not implemented yet!\n");
+		return;
+	}
+	opcode &= 0x7f; /* Mask away LST bit */
+	
+	switch( opcode) {
+	case GET_INFO_BASE:
+		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		break;
+	case GET_VALUE_BY_CLASS:
+		iriap_getvaluebyclass_indication( self, skb);
+		break;
+	}
+}
+
+void iriap_watchdog_timer_expired( unsigned long data)
+{
+	struct iriap_cb *self = ( struct iriap_cb *) data;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	DEBUG( 0, __FUNCTION__ "() Timeout! closing myself!\n");
+	iriap_close( self);
+}
+
+#ifdef CONFIG_PROC_FS
+
+static char *ias_value_types[] = {
+	"IAS_MISSING",
+	"IAS_INTEGER",
+	"IAS_OCT_SEQ",
+	"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)
+{
+	struct ias_object *obj;
+	struct ias_attrib *attrib;
+	unsigned long flags;
+
+	ASSERT( objects != NULL, return 0;);
+
+	save_flags( flags);
+	cli();
+
+	len = 0;
+
+	len += sprintf( buf+len, "LM-IAS Objects:\n");
+
+	/* List all objects */
+	obj = (struct ias_object *) hashbin_get_first( objects);
+	while ( obj != NULL) {
+		ASSERT( obj->magic == IAS_OBJECT_MAGIC, return 0;);
+
+		len += sprintf( buf+len, "name: %s, ", obj->name);
+		len += sprintf( buf+len, "id=%d", obj->id);
+		len += sprintf( buf+len, "\n");
+
+		/* List all attributes for this object */
+		attrib = (struct ias_attrib *) 
+			hashbin_get_first( obj->attribs);
+		while ( attrib != NULL) {
+			ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
+
+			len += sprintf( buf+len, " - Attribute name: \"%s\", ",
+ 					attrib->name);
+			len += sprintf( buf+len, "value[%s]: ", 
+					ias_value_types[ attrib->value->type]);
+			
+			switch( attrib->value->type) {
+			case IAS_INTEGER:
+				len += sprintf( buf+len, "%d\n", 
+						attrib->value->t.integer);
+				break;
+			case IAS_STRING:
+				len += sprintf( buf+len, "\"%s\"\n", 
+						attrib->value->t.string);
+				break;
+			case IAS_OCT_SEQ:
+				len += sprintf( buf+len, "octet sequence\n");
+				break;
+			case IAS_MISSING:
+				len += sprintf( buf+len, "missing\n");
+				break;
+			default:
+				DEBUG( 0, __FUNCTION__ 
+				       "(), Unknown value type!\n");
+				return -1;
+			}
+			len += sprintf( buf+len, "\n");
+			
+			attrib = ( struct ias_attrib *) 
+				hashbin_get_next( obj->attribs);
+		}
+	        obj = ( struct ias_object *) hashbin_get_next( objects);
+ 	} 
+	restore_flags( flags);
+
+	return len;
+}
+
+#endif /* PROC_FS */
diff -u --recursive --new-file v2.1.131/linux/net/irda/iriap_event.c linux/net/irda/iriap_event.c
--- v2.1.131/linux/net/irda/iriap_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/iriap_event.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,529 @@
+/*********************************************************************
+ *                
+ * Filename:      iriap_event.c
+ * Version:       0.1
+ * Description:   IAP Finite State Machine
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/iriap_event.h>
+
+static void state_s_disconnect   ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_connecting   ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_call         ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+
+static void state_s_make_call    ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_calling      ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_outstanding  ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_replying     ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_s_wait_active  ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+
+static void state_r_disconnect   ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_r_call         ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_r_waiting      ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_r_wait_active  ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_r_receiving    ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_r_execute      ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+static void state_r_returning    ( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb);
+
+static void (*iriap_state[])( struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb) = { 
+	/* Client FSM */
+	state_s_disconnect,
+	state_s_connecting,
+	state_s_call,
+	
+	/* S-Call FSM */
+	state_s_make_call,
+	state_s_calling,
+	state_s_outstanding,
+	state_s_replying,
+	state_s_wait_for_call,
+	state_s_wait_active,
+
+	/* Server FSM */
+	state_r_disconnect,
+	state_r_call,
+
+	/* R-Connect FSM */
+	state_r_waiting,
+	state_r_wait_active,
+	state_r_receiving,
+	state_r_execute,
+	state_r_returning,
+};
+
+void iriap_next_client_state( struct iriap_cb *self, IRIAP_STATE state) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+ 	switch ( state) { 
+ /* 	case S_DISCONNECT: DEBUG( 0, "IAP Client = S_DISCONNECT\n"); break;  */
+/*  	case S_CONNECTING: DEBUG( 0, "IAP Client = S_CONNECTING\n"); break;  */
+/*  	case S_CALL:       DEBUG( 0, "IAP Client = S_CALL\n");       break;  */
+ 	default: 
+ 		break; 
+ 	} 
+	self->client_state = state;
+}
+
+void iriap_next_call_state( struct iriap_cb *self, IRIAP_STATE state) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+/* 	switch ( state) { */
+/* 	case S_MAKE_CALL:     DEBUG( 0, "IAP Call = S_MAKE_CALL\n"); break; */
+/* 	case S_CALLING:       DEBUG( 0, "IAP Call = S_CALLING\n"); break; */
+/* 	case S_OUTSTANDING:   DEBUG( 0, "IAP Call = S_OUTSTANDING\n");break; */
+/* 	case S_REPLYING:      DEBUG( 0, "IAP Call = S_REPLYING\n"); break; */
+/* 	case S_WAIT_FOR_CALL: DEBUG( 0, "IAP Call = S_WAIT_FOR_CALL\n"); break; */
+/* 	case S_WAIT_ACTIVE:   DEBUG( 0, "IAP Call = S_WAIT_ACTIVE\n"); break; */
+/* 	default: */
+/* 		break; */
+/* 	} */
+	self->call_state = state;
+}
+
+void iriap_next_server_state( struct iriap_cb *self, IRIAP_STATE state)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	self->server_state = state;
+}
+
+void iriap_next_r_connect_state( struct iriap_cb *self, IRIAP_STATE state)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	
+	self->r_connect_state = state;
+}
+
+void iriap_do_client_event( struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	(*iriap_state[ self->client_state]) ( self, event, skb);
+}
+
+void iriap_do_call_event( struct iriap_cb *self, IRIAP_EVENT event, 
+			  struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	
+	(*iriap_state[ self->call_state]) ( self, event, skb);
+}
+
+void iriap_do_server_event( struct iriap_cb *self, IRIAP_EVENT event, 
+			    struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	
+	(*iriap_state[ self->server_state]) ( self, event, skb);
+}
+
+void iriap_do_r_connect_event( struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+	
+	(*iriap_state[ self->r_connect_state]) ( self, event, skb);
+}
+
+
+/*
+ * Function state_s_disconnect (event, skb)
+ *
+ *    S-Disconnect, The device has no LSAP connection to a particular
+ *    remote device.
+ */
+static void state_s_disconnect( struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	switch( event) {
+	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);
+		break;
+	case IAP_LM_DISCONNECT_INDICATION:
+		break;
+	default:
+		DEBUG( 0, "state_s_disconnect: Unknown event %d\n", event);
+		break;
+	}
+}
+
+/*
+ * Function state_s_connecting (self, event, skb)
+ *
+ *    S-Connecting
+ *
+ */
+static void state_s_connecting( struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IAS_MAGIC, return;);
+
+	switch( event) {
+	case IAP_LM_CONNECT_CONFIRM:
+		/*
+		 *  Jump to S-Call FSM
+		 */
+		iriap_do_call_event( self, IAP_CALL_REQUEST, skb);
+		/* iriap_call_request( self, 0,0,0); */
+		iriap_next_client_state( self, S_CALL);
+		break;
+	case IAP_LM_DISCONNECT_INDICATION:
+		/* Abort calls */
+		iriap_next_call_state( self, S_MAKE_CALL);
+		iriap_next_client_state( self, S_DISCONNECT);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}
+}
+
+/*
+ * Function state_s_call (self, event, skb)
+ *
+ *    S-Call, The device can process calls to a specific remote
+ *    device. Whenever the LSAP connection is disconnected, this state
+ *    catches that event and clears up 
+ */
+static void state_s_call( struct iriap_cb *self, IRIAP_EVENT event, 
+			  struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+
+	switch( event) {
+	case IAP_LM_DISCONNECT_INDICATION:
+		/* Abort calls */
+		iriap_next_call_state( self, S_MAKE_CALL);
+		iriap_next_client_state( self, S_DISCONNECT);
+		break;
+	default:
+		DEBUG( 0, "state_s_call: Unknown event %d\n", event);
+		break;
+	}
+}
+
+/*
+ * Function state_s_make_call (event, skb)
+ *
+ *    S-Make-Call
+ *
+ */
+static void state_s_make_call( struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+
+	switch( event) {
+	case IAP_CALL_REQUEST:
+		irlmp_data_request( self->lsap, self->skb);
+		iriap_next_call_state( self, S_OUTSTANDING);
+		break;
+	default:
+		DEBUG( 0, "state_s_make_call: Unknown event %d\n", event);
+		break;
+	}
+	if ( skb) {
+		dev_kfree_skb( skb);
+	}
+}
+
+/*
+ * Function state_s_calling (event, skb)
+ *
+ *    S-Calling
+ *
+ */
+static void state_s_calling( struct iriap_cb *self, IRIAP_EVENT event, 
+			     struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+}
+
+/*
+ * Function state_s_outstanding (event, skb)
+ *
+ *    S-Outstanding, The device is waiting for a response to a command
+ *
+ */
+static void state_s_outstanding( struct iriap_cb *self, IRIAP_EVENT event, 
+				 struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+
+	switch( event) {
+	case IAP_RECV_F_LST:
+		iriap_send_ack( self);
+		/*LM_Idle_request(idle); */
+
+		dev_kfree_skb( skb);
+		iriap_next_call_state( self, S_WAIT_FOR_CALL);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}		
+}
+
+/*
+ * Function state_s_replying (event, skb)
+ *
+ *    S-Replying, The device is collecting a multiple part response
+ */
+static void state_s_replying( struct iriap_cb *self, IRIAP_EVENT event, 
+			      struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+}
+
+/*
+ * Function state_s_wait_for_call (event, skb)
+ *
+ *    S-Wait-for-Call
+ *
+ */
+static void state_s_wait_for_call( struct iriap_cb *self, IRIAP_EVENT event, 
+				   struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+}
+
+
+/*
+ * Function state_s_wait_active (event, skb)
+ *
+ *    S-Wait-Active
+ *
+ */
+static void state_s_wait_active( struct iriap_cb *self, IRIAP_EVENT event, 
+				 struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+}
+
+/**************************************************************************
+ * 
+ *  Server FSM 
+ *
+ **************************************************************************/
+
+/*
+ * Function state_r_disconnect (self, event, skb)
+ *
+ *    LM-IAS server is disconnected (not processing any requests!)
+ *
+ */
+static void state_r_disconnect( struct iriap_cb *self, IRIAP_EVENT event, 
+				struct sk_buff *skb) 
+{
+	struct sk_buff *tx_skb;
+	
+	switch( event) {
+	case IAP_LM_CONNECT_INDICATION:
+		tx_skb = dev_alloc_skb( 64);
+		if ( tx_skb == NULL) {
+			DEBUG( 0,"state_r_disconnect: "
+			       "Could not allocate an sk_buff of length %d\n",
+			       64);
+			return;
+		}
+
+		/* Reserve space for MUX_CONTROL and LAP header */
+		skb_reserve( tx_skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		
+		irlmp_connect_response( self->lsap, tx_skb);
+		/*LM_Idle_request(idle); */
+		
+		iriap_next_server_state( self, R_CALL);
+		
+		/*
+		 *  Jump to R-Connect FSM, we skip R-Waiting since we do not
+		 *  care about LM_Idle_request()!
+		 */
+		iriap_next_r_connect_state( self, R_RECEIVING);
+
+		if (skb)
+			dev_kfree_skb( skb);
+		
+		break;
+	default:
+		DEBUG( 0, "state_r_disconnect: Unknown event %d\n", event);
+		break;
+	}		
+}
+
+/*
+ * Function state_r_call (self, event, skb)
+ *
+ *    
+ *
+ */
+static void state_r_call( struct iriap_cb *self, IRIAP_EVENT event, 
+			  struct sk_buff *skb) 
+{
+	DEBUG( 4, "state_r_call()\n");
+
+	switch( event) {
+	case IAP_LM_DISCONNECT_INDICATION:
+		/* Abort call */
+		iriap_next_server_state( self, R_DISCONNECT);
+		iriap_next_r_connect_state( self, R_WAITING);
+		
+		break;
+	default:
+		DEBUG( 0, "state_r_call, unknown event!\n");
+		break;
+	}
+}
+
+/* 
+ *  R-Connect FSM 
+*/
+
+/*
+ * Function state_r_waiting (self, event, skb)
+ *
+ *    
+ *
+ */
+static void state_r_waiting( struct iriap_cb *self, IRIAP_EVENT event, 
+			     struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+}
+
+static void state_r_wait_active( struct iriap_cb *self, 
+				 IRIAP_EVENT event, struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented\n");
+}
+
+/*
+ * Function state_r_receiving (self, event, skb)
+ *
+ *    We are receiving a command
+ *
+ */
+static void state_r_receiving( struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	switch( event) {
+	case IAP_RECV_F_LST:
+		iriap_next_r_connect_state( self, R_EXECUTE);
+	 		
+		iriap_call_indication( self, skb);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
+		break;
+	}
+
+}
+
+/*
+ * Function state_r_execute (self, event, skb)
+ *
+ *    The server is processing the request
+ *
+ */
+static void state_r_execute( struct iriap_cb *self, IRIAP_EVENT event, 
+			     struct sk_buff *skb) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( skb != NULL, return;);
+	
+	if ( !self || self->magic != IAS_MAGIC) {
+		DEBUG( 0, "state_r_execute: bad pointer self\n");
+		return;
+	}	
+
+	switch( event) {
+	case IAP_CALL_RESPONSE:
+		/*  
+		 *  Since we don't implement the Waiting state, we return
+		 *  to state Receiving instead, DB.
+		 */
+		iriap_next_r_connect_state( self, R_RECEIVING);
+	 		
+		irlmp_data_request( self->lsap, skb);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), unknown event!\n");
+		break;
+	}
+}
+
+static void state_r_returning( struct iriap_cb *self, IRIAP_EVENT event, 
+			       struct sk_buff *skb) 
+{
+	DEBUG( 0, __FUNCTION__ "(), event=%d\n", event);
+
+	switch( event) {
+	case IAP_RECV_F_LST:
+		
+		break;
+	default:
+		break;
+	}
+}
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irias_object.c linux/net/irda/irias_object.c
--- v2.1.131/linux/net/irda/irias_object.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irias_object.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,500 @@
+/*********************************************************************
+ *                
+ * Filename:      irias_object.c
+ * Version:       0.1
+ * Description:   IAS object database and functions
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Thu Oct  1 22:50:04 1998
+ * Modified at:   Sat Dec  5 13:54:39 1998
+ * 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/string.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irias_object.h>
+
+hashbin_t *objects = NULL;
+
+/*
+ *  Used when a missing value needs to be returned
+ */
+struct ias_value missing = {
+        IAS_MISSING,	0,	0,	{ 0 }
+};
+
+/*
+ * Function strdup (str)
+ *
+ *    My own kernel version of strdup!
+ *
+ */
+char *strdup( char *str)
+{
+	char *new_str;
+	
+	if ( str == NULL)
+		return NULL;
+
+	ASSERT( strlen( str) < 64, return NULL;);
+	
+        new_str = kmalloc( strlen( str)+1, GFP_ATOMIC);
+        if ( new_str == NULL)
+		return NULL;
+	
+	strcpy( new_str, str);
+	
+	return new_str;
+}
+
+/*
+ * Function ias_new_object (name, id)
+ *
+ *    Create a new IAS object
+ *
+ */
+struct ias_object *irias_new_object( char *name, int id)
+{
+        struct ias_object *obj;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	obj = (struct ias_object *) kmalloc( sizeof( struct ias_object), 
+					     GFP_ATOMIC);
+	if ( obj == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to allocate object!\n");
+		return NULL;
+	}
+	memset( obj, 0, sizeof( struct ias_object));
+
+	obj->magic = IAS_OBJECT_MAGIC;
+	obj->name = strdup( name);
+	obj->id = id;
+
+	obj->attribs = hashbin_new( HB_LOCAL);
+	
+	return obj;
+}
+
+/*
+ * Function irias_delete_attrib (attrib)
+ *
+ *    Delete given attribute and deallocate all its memory
+ *
+ */
+void __irias_delete_attrib( struct ias_attrib *attrib)
+{
+	ASSERT( attrib != NULL, return;);
+	ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;);
+
+	if ( attrib->name)
+		kfree( attrib->name);
+
+	irias_delete_value( attrib->value);
+	attrib->magic = ~IAS_ATTRIB_MAGIC;
+	
+	kfree( attrib);
+}
+
+/*
+ * Function irias_delete_object (obj)
+ *
+ *    Remove object from hashbin and deallocate all attributes assosiated with
+ *    with this object and the object itself
+ *
+ */
+void __irias_delete_object( struct ias_object *obj) 
+{
+	ASSERT( obj != NULL, return;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	
+	if ( obj->name)
+		kfree( obj->name);
+	
+	hashbin_delete( obj->attribs, (FREE_FUNC) __irias_delete_attrib);
+	
+	obj->magic = ~IAS_OBJECT_MAGIC;
+	
+	kfree( obj);
+}
+
+/*
+ * Function irias_remove_object (obj)
+ *
+ *    Remove object with give name from the LM-IAS object database
+ *
+ */
+void irias_delete_object( char *obj_name)
+{
+	struct ias_object *obj;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( obj_name != NULL, return;);
+
+	obj = hashbin_remove( objects, 0, obj_name);
+
+	__irias_delete_object( obj);
+}
+
+/*
+ * Function irias_insert_object (obj)
+ *
+ *    Insert an object into the LM-IAS database
+ *
+ */
+void irias_insert_object( struct ias_object *obj)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( obj != NULL, return;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	
+	hashbin_insert( objects, (QUEUE *) obj, 0, obj->name);
+}
+
+/*
+ * Function irias_find_object (name)
+ *
+ *    Find object with given name
+ *
+ */
+struct ias_object *irias_find_object( char *name)
+{
+	ASSERT( name != NULL, return NULL;);
+
+	return hashbin_find( objects, 0, name);
+}
+
+/*
+ * Function irias_find_attrib (obj, name)
+ *
+ *    Find named attribute in object
+ *
+ */
+struct ias_attrib *irias_find_attrib( struct ias_object *obj, char *name)
+{
+	struct ias_attrib *attrib;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( obj != NULL, return NULL;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return NULL;);
+	ASSERT( name != NULL, return NULL;);
+
+	attrib = hashbin_find( obj->attribs, 0, name);
+	if ( attrib == NULL)
+		return NULL;
+
+	return attrib;
+}
+
+/*
+ * Function irias_add_attribute (obj, attrib)
+ *
+ *    Add attribute to object
+ *
+ */
+void irias_add_attrib( struct ias_object *obj, struct ias_attrib *attrib)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( obj != NULL, return;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	
+	ASSERT( attrib != NULL, return;);
+	ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return;);
+
+	hashbin_insert( obj->attribs, (QUEUE *) attrib, 0, attrib->name);
+}
+
+/*
+ * Function irias_object_change_attribute (obj_name, attrib_name, new_value)
+ *
+ *    Change the value of an objects attribute.
+ *
+ *    TODO: not tested yet!
+ */
+int irias_object_change_attribute( char *obj_name, char *attrib_name, 
+				   struct ias_value *new_value) 
+{
+	struct ias_object *obj;
+	struct ias_attrib *attrib;
+
+	/* Find object */
+	obj = hashbin_find( objects, 0, obj_name);
+	if ( obj == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to find object: %s\n",
+		       obj_name);
+		return -1;
+	}
+
+	/* Find attribute */
+	attrib = hashbin_find( obj->attribs, 0, attrib_name);
+	if ( attrib == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to find attribute: %s\n",
+		       attrib_name);
+		return -1;
+	}
+
+	if ( attrib->value->type != new_value->type) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), changing value type not allowed!\n");
+		return -1;
+	}
+
+	/* Delete old value */
+	irias_delete_value( attrib->value);
+	
+	/* Insert new value */
+	attrib->value = new_value;
+
+	/* Success */
+	return 0;
+}
+
+/*
+ * Function irias_object_add_integer_attrib (obj, name, value)
+ *
+ *    Add an integer attribute to an LM-IAS object
+ *
+ */
+void irias_add_integer_attrib( struct ias_object *obj, char *name, int value)
+{
+	struct ias_attrib *attrib;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( obj != NULL, return;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	ASSERT( name != NULL, return;);
+	
+	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
+						GFP_ATOMIC);
+	if ( attrib == NULL) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to allocate attribute!\n");
+		return;
+	}
+	memset( attrib, 0, sizeof( struct ias_attrib));
+
+	attrib->magic = IAS_ATTRIB_MAGIC;
+	attrib->name = strdup( name);
+/* 	attrib->attr = NULL; */
+
+	/* Insert value */
+	attrib->value = irias_new_integer_value( value);
+	
+	irias_add_attrib( obj, attrib);
+}
+
+ /*
+ * Function irias_add_octseq_attrib (obj, name, octet_seq, len)
+ *
+ *    Add a octet sequence attribute to an LM-IAS object
+ *
+ */
+
+void irias_add_octseq_attrib( struct ias_object *obj, char *name, 
+			      __u8 *octets, int len)
+{
+	struct ias_attrib *attrib;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	DEBUG( 0, __FUNCTION__ ": name=%s\n", name);
+	DEBUG( 0, __FUNCTION__ ": len=%d\n", len);
+	
+	ASSERT( obj != NULL, return;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+	
+	ASSERT( name != NULL, return;);
+	ASSERT( octets != NULL, return;);
+	ASSERT( len < 55, return;);          /* FIXME: must be 1024, but... */
+	
+	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
+						GFP_ATOMIC);
+	if ( attrib == NULL) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to allocate attribute!\n");
+		return;
+	}
+	memset( attrib, 0, sizeof( struct ias_attrib));
+	
+	attrib->magic = IAS_ATTRIB_MAGIC;
+	attrib->name = strdup( name);
+	
+	attrib->value = irias_new_octseq_value( octets, len);
+	
+	irias_add_attrib( obj, attrib);
+}
+
+/*
+ * Function irias_object_add_string_attrib (obj, string)
+ *
+ *    Add a string attribute to an LM-IAS object
+ *
+ */
+void irias_add_string_attrib( struct ias_object *obj, char *name, char *value)
+{
+	struct ias_attrib *attrib;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	DEBUG( 4, __FUNCTION__ ": name=%s\n", name);
+	DEBUG( 4, __FUNCTION__ ": name=%s\n", value);
+	
+	ASSERT( obj != NULL, return;);
+	ASSERT( obj->magic == IAS_OBJECT_MAGIC, return;);
+
+	ASSERT( name != NULL, return;);
+	ASSERT( value != NULL, return;);
+	
+	attrib = (struct ias_attrib *) kmalloc( sizeof( struct ias_attrib), 
+						GFP_ATOMIC);
+	if ( attrib == NULL) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unable to allocate attribute!\n");
+		return;
+	}
+	memset( attrib, 0, sizeof( struct ias_attrib));
+
+	attrib->magic = IAS_ATTRIB_MAGIC;
+	attrib->name = strdup( name);
+
+	attrib->value = irias_new_string_value( value);
+
+	irias_add_attrib( obj, attrib);
+}
+
+/*
+ * Function irias_new_integer_value (integer)
+ *
+ *    Create new IAS integer value
+ *
+ */
+struct ias_value *irias_new_integer_value( int integer)
+{
+	struct ias_value *value;
+
+	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
+	if ( value == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+		return NULL;
+	}
+	memset( value, 0, sizeof( struct ias_value));
+
+	value->type = IAS_INTEGER;
+	value->len = 4;
+	value->t.integer = integer;
+
+	return value;
+}
+
+/*
+ * Function irias_new_string_value (string)
+ *
+ *    Create new IAS string value
+ *
+ */
+struct ias_value *irias_new_string_value( char *string)
+{
+	struct ias_value *value;
+
+	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
+	if ( value == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+		return NULL;
+	}
+	memset( value, 0, sizeof( struct ias_value));
+
+	value->type = IAS_STRING;
+	value->charset = CS_ASCII;
+	value->len = strlen( string);
+	value->t.string = strdup( string);
+
+	return value;
+}
+
+
+/*
+ * Function irias_new_octseq_value (octets, len)
+ *
+ *    Create new IAS octet-sequence value
+ *
+ */
+struct ias_value *irias_new_octseq_value( __u8 *octseq , int len)
+{
+	struct ias_value *value;
+
+	ASSERT(len <= 55, return NULL;); /*FIXME: must be 1024, but.....*/
+
+	value = kmalloc( sizeof( struct ias_value), GFP_ATOMIC);
+	if ( value == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to kmalloc!\n");
+		return NULL;
+	}
+	memset( value, 0, sizeof( struct ias_value));
+
+	value->type = IAS_OCT_SEQ;
+	value->len = len;
+
+	value->t.oct_seq = kmalloc(len, GFP_ATOMIC);
+	if( value->t.oct_seq == NULL){
+		DEBUG(0, __FUNCTION__"(), Unable to kmalloc!\n");
+		return NULL;
+	}
+	memcpy(value->t.oct_seq, octseq , len);
+	return value;
+}
+
+/*
+ * Function irias_delete_value (value)
+ *
+ *    Delete IAS value
+ *
+ */
+void irias_delete_value( struct ias_value *value)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( value != NULL, return;);
+
+	switch( value->type) {
+	case IAS_INTEGER: /* Fallthrough */
+	case IAS_MISSING:
+		/* No need to deallocate */
+		break;
+	case IAS_STRING:
+		/* If string, deallocate string */
+		if ( value->t.string != NULL)
+			kfree( value->t.string);
+		break;
+	case IAS_OCT_SEQ:
+		/* If byte stream, deallocate byte stream */
+		 if ( value->t.oct_seq != NULL)
+			 kfree(value->t.oct_seq);
+		 break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown value type!\n");
+		break;
+	}
+	kfree( value);
+}
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlan/Config.in linux/net/irda/irlan/Config.in
--- v2.1.131/linux/net/irda/irlan/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/Config.in	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,7 @@
+
+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.1.131/linux/net/irda/irlan/Makefile linux/net/irda/irlan/Makefile
--- v2.1.131/linux/net/irda/irlan/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/Makefile	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,52 @@
+#
+# Makefile for the Linux IrDA IrLAN protocol layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+MOD_LIST_NAME := IRDA_MODULES
+O_TARGET := irlan.o
+O_OBJS	 := irlan_common.o irlan_eth.o irlan_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.1.131/linux/net/irda/irlan/irlan_cli.c linux/net/irda/irlan/irlan_cli.c
--- v2.1.131/linux/net/irda/irlan/irlan_cli.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_cli.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,678 @@
+/*********************************************************************
+ *                
+ * 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 Dec 14 10:44:07 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/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( 0, "--> irlan_client_cleanup\n");
+
+	irlmp_unregister_layer( S_LAN, CLIENT);
+
+	DEBUG( 4, "irlan_client_cleanup -->\n");
+}
+
+/*
+ * 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( 0, "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( 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_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.1.131/linux/net/irda/irlan/irlan_cli_event.c linux/net/irda/irlan/irlan_cli_event.c
--- v2.1.131/linux/net/irda/irlan/irlan_cli_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_cli_event.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,494 @@
+/*********************************************************************
+ *                
+ * 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.1.131/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.1.131/linux/net/irda/irlan/irlan_common.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_common.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,896 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_common.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 10:43:05 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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/config.h>
+#include <linux/module.h> 
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.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/iriap.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlan_common.h>
+
+static void __irlan_close( struct irlan_cb *self);
+
+/*
+ *  Master structure
+ */
+hashbin_t *irlan = NULL;
+
+#ifdef CONFIG_PROC_FS
+static int irlan_proc_read( char *buf, char **start, off_t offset, 
+			    int len, int unused);
+
+extern struct proc_dir_entry proc_irda;
+
+struct proc_dir_entry proc_irlan = {
+	0, 5, "irlan",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL,
+	&irlan_proc_read,
+};
+#endif
+
+/*
+ * Function irlan_init (void)
+ *
+ *    Initialize IrLAN layer
+ *
+ */
+__initfunc(int irlan_init( void))
+{
+	/* Allocate master array */
+	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);
+#endif /* CONFIG_PROC_FS */
+
+	return 0;
+}
+
+void irlan_cleanup(void) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+#ifdef CONFIG_PROC_FS
+	proc_unregister( &proc_irda, proc_irlan.low_ino);
+#endif
+	/*
+	 *  Delete hashbin and close all irlan client instances in it
+	 */
+	hashbin_delete( irlan, (FREE_FUNC) __irlan_close);
+}
+
+
+/*
+ * Function irlan_open (void)
+ *
+ *    
+ *
+ */
+struct irlan_cb *irlan_open(void)
+{
+	struct irlan_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* 
+	 *  Initialize the irlan structure. 
+	 */
+	self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
+	if ( self == NULL)
+		return NULL;
+	
+	memset( self, 0, sizeof( struct irlan_cb));
+
+	/*
+	 *  Initialize local device structure
+	 */
+	self->magic = IRLAN_MAGIC;
+
+	return self;
+}
+/*
+ * Function irlan_close (self)
+ *
+ *    This function closes and deallocates the IrLAN client instances. Be 
+ *    aware that other functions which calles client_close() must call 
+ *    hashbin_remove() first!!!
+ *
+ */
+void __irlan_close( struct irlan_cb *self)
+{
+	DEBUG( 4, __FUNCTION__ "()\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);
+
+	/*
+	 *  Make sure that nobody uses this instance anymore!
+	 */
+	self->magic = 0;
+	
+	/*
+	 *  Dealloacte structure
+	 */
+	kfree( self);
+}
+
+/*
+ * Function irlan_close (self)
+ *
+ *    
+ *
+ */
+void irlan_close( struct irlan_cb *self)
+{
+	struct irlan_cb *entry;
+	
+	DEBUG( 4, __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_get_provider_info (self)
+ *
+ *    Send Get Provider Information command to peer IrLAN layer
+ *
+ */
+void irlan_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, __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);
+	
+	frame = skb->data;
+	
+ 	frame[0] = CMD_GET_PROVIDER_INFO;
+	frame[1] = 0x00;                 /* Zero parameters */
+	
+	irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_open_data_channel (self)
+ *
+ *    Send an Open Data Command to provider
+ *
+ */
+void irlan_open_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 == 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);
+	
+	frame = skb->data;
+	
+	/* Build frame */
+ 	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"); */
+
+/* 	self->use_udata = TRUE; */
+
+	irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_open_unicast_addr (self)
+ *
+ *    Make IrLAN provider accept ethernet frames addressed to the unicast 
+ *    address.
+ *
+ */
+void irlan_open_unicast_addr( 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 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);
+	
+	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"); 
+	
+	irttp_data_request( self->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
+ *    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.
+ */
+void irlan_set_broadcast_filter( struct irlan_cb *self, int status) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	
+	/* Should only be used by client */
+	if (!self->client)
+		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);
+	
+	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"); 
+	else
+		insert_string_param( skb, "FILTER_MODE", "NONE"); 
+	
+	irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_set_multicast_filter (self, status)
+ *
+ *    Make IrLAN provider accept ethernet frames addressed to the multicast
+ *    address. 
+ *
+ */
+void irlan_set_multicast_filter( struct irlan_cb *self, int status) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+	/* Should only be used by client */
+	if (!self->client)
+		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);
+	
+	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"); 
+	else
+		insert_string_param( skb, "FILTER_MODE", "NONE"); 
+	
+	irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_get_unicast_addr (self)
+ *
+ *    Retrives the unicast address from the IrLAN provider. This address
+ *    will be inserted into the devices structure, so the ethernet layer
+ *    can construct its packets.
+ *
+ */
+void irlan_get_unicast_addr( 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, "irlan_client_get_unicast_addr: "
+		       "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_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"); 
+	
+	irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_get_media_char (self)
+ *
+ *    
+ *
+ */
+void irlan_get_media_char( 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_media_char: "
+		       "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;
+	
+	/* Build frame */
+ 	frame[0] = CMD_GET_MEDIA_CHAR;
+	frame[1] = 0x01; /* One parameter */
+	
+	insert_string_param( skb, "MEDIA", "802.3");
+	
+	irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function insert_byte_param (skb, param, value)
+ *
+ *    Insert byte parameter into frame
+ *
+ */
+int 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;
+
+	frame[n++] = value;
+	
+	return len_param+len_value+3;
+}
+
+/*
+ * Function insert_string (skb, param, value)
+ *
+ *    Insert string parameter into frame
+ *
+ */
+int insert_string_param( struct sk_buff *skb, char *param, char *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 = strlen( value);
+
+	/*
+	 *  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;
+}
+
+/*
+ * 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)
+{
+	__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;
+}
+
+/*
+ * Function insert_param (skb, param, value, byte)
+ *
+ *    Insert parameter at end of buffer, structure of a parameter is:
+ *
+ *    -----------------------------------------------------------------------
+ *    | 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) 
+{
+	__u8 *frame;
+	__u8 len_param;
+	__u16 len_value;
+	int n;
+	
+	if ( skb == NULL) {
+		DEBUG( 0, "insert_param: 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);
+		break;
+	case 2:
+		len_value = 1;
+		break;
+	case 3:
+		len_value = 2;
+		break;
+	default:
+		DEBUG( 0, "Error in insert_param!\n");
+		return 0;
+		break;
+	}
+	
+	/*
+	 *  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;
+
+	/* Insert value */
+	switch (type) {
+	case 1:
+		memcpy( frame+n, value_char, len_value); n+=len_value;
+		break;
+	case 2:
+		frame[n++] = value_byte;
+		break;
+	case 3:
+		frame[n++] = value_short & 0xff;
+		frame[n++] = (value_short >> 8) & 0xff;
+		break;
+	default:
+		break;
+	}
+	ASSERT( n == (len_param+len_value+3), return 0;);
+
+	return len_param+len_value+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.
+ * 
+ */
+int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len)
+{
+	__u8 name_len;
+	__u16 val_len;
+	int n=0;
+
+	DEBUG( 4, "irlan_get_response_param()\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;
+	}
+	
+	/* get parameter name */
+	memcpy( name, buf+n, name_len);
+	name[ name_len] = '\0';
+	n+=name_len;
+	
+	/*  
+	 *  Get length of parameter value ( 2 bytes in little endian 
+	 *  format) 
+	 */
+	val_len = buf[n++] & 0xff;
+	val_len |= buf[n++] << 8;
+	
+	if (val_len > 1016) {
+		DEBUG( 0, __FUNCTION__ "(), parameter length to long\n");
+		return -1;
+	}
+	
+	*len = val_len;
+
+	/* get parameter value */
+	memcpy( value, buf+n, val_len);
+	value[ val_len] = '\0';
+	n+=val_len;
+	
+	DEBUG( 4, "Parameter: %s ", name); 
+	DEBUG( 4, "Value: %s\n", value); 
+
+	return n;
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irlan_client_proc_read (buf, start, offset, len, unused)
+ *
+ *    Give some info to the /proc file system
+ */
+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;);
+	
+	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, "\n");
+
+		self = ( struct irlan_cb *) hashbin_get_next( irlan);
+		DEBUG( 4, "self=%p\n", self);
+ 	} 
+	return len;
+}
+#endif
+
+/*
+ * Function print_ret_code (code)
+ *
+ *    Print return code of request to peer IrLAN layer.
+ *
+ */
+void print_ret_code( __u8 code) 
+{
+	switch( code) {
+	case 0:
+		printk( KERN_INFO "Success\n");
+		break;
+	case 1:
+		printk( KERN_WARNING "Insufficient resources\n");
+		break;
+	case 2:
+		printk( KERN_WARNING "Invalid command format\n");
+		break;
+	case 3:
+		printk( KERN_WARNING "Command not supported\n");
+		break;
+	case 4:
+		printk( KERN_WARNING "Parameter not supported\n");
+		break;
+	case 5:
+		printk( KERN_WARNING "Value not supported\n");
+		break;
+	case 6:
+		printk( KERN_WARNING "Not open\n");
+		break;
+	case 7:
+		printk( KERN_WARNING "Authentication required\n");
+		break;
+	case 8:
+		printk( KERN_WARNING "Invalid password\n");
+		break;
+	case 9:
+		printk( KERN_WARNING "Protocol error\n");
+		break;
+	case 255:
+		printk( KERN_WARNING "Asynchronous status\n");
+		break;
+	}
+}
+
+#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.c\n");
+
+	irlan_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_cleanup();
+
+	DEBUG( 4, "irlan, cleanup_module -->\n");
+}
+
+#endif /* MODULE */
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.1.131/linux/net/irda/irlan/irlan_eth.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_eth.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,396 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_eth.c
+ * Version:       
+ * Description:   
+ * 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 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, 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/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <net/arp.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlan_common.h>
+#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)
+{
+	struct irlan_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	self = (struct irlan_cb *) dev->priv;
+
+	ASSERT( self != NULL, return 0;);
+	ASSERT( self->magic == IRLAN_MAGIC, return 0;);
+
+	if ( dev->tbusy) {
+		/*
+		 * 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) 
+ 			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);
+	
+	/* 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;);
+
+		/*  Free original skb, and use the new one */
+		dev_kfree_skb( skb);
+		skb = new_skb;
+	} 
+
+	dev->trans_start = jiffies;
+	self->stats.tx_packets++;
+	self->stats.tx_bytes += skb->len; 
+
+	/*
+	 *  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);
+		dev->tbusy = 0;
+	
+		return 0;
+	}
+
+	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
+		 *  and don't deallocate the frame, but that is dangerous
+		 *  since it's possible that we have replaced the original
+		 *  skb with a new one with larger headroom, and that would
+		 *  really confuse do_dev_queue_xmit() in dev.c! I have
+		 *  tried :-) DB
+		 */
+		DEBUG( 4, __FUNCTION__ "(), Dropping frame\n");
+		dev_kfree_skb( skb);
+		++self->stats.tx_dropped;
+		
+		return 0;
+	}
+	dev->tbusy = 0;
+	
+	return 0;
+}
+
+/*
+ * Function irlan_eth_rx (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)
+{
+	struct irlan_cb *self;
+
+	self = ( struct irlan_cb *) instance;
+
+	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;);
+		
+	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 */
+	
+	netif_rx( skb);   /* Eat it! */
+	
+	self->stats.rx_packets++;
+	self->stats.rx_bytes += skb->len; 
+}
+
+/*
+ * Function irlan_eth_flow (status)
+ *
+ *    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)
+{
+	struct irlan_cb *self;
+	struct device *dev;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	self = (struct irlan_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLAN_MAGIC, return;);
+	
+	dev = &self->dev;
+
+	ASSERT( dev != NULL, return;);
+	
+	switch ( flow) {
+	case FLOW_STOP:
+		DEBUG( 4, "IrLAN, stopping Ethernet layer\n");
+
+		dev->tbusy = 1;
+		break;
+	case FLOW_START:
+		/* 
+		 *  Tell upper layers that its time to transmit frames again
+		 */
+		DEBUG( 4, "IrLAN, starting Ethernet layer\n");
+
+		dev->tbusy = 0;
+
+		/* 
+		 *  Ready to receive more frames, so schedule the network
+		 *  layer
+		 */
+		mark_bh( NET_BH);		
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+	}
+}
+
+/*
+ * Function irlan_eth_rebuild_header (buff, dev, dest, skb)
+ *
+ *    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)
+{
+	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);
+
+	/* return 0; */
+}
+
+/*
+ * Function set_multicast_list (dev)
+ *
+ *    Configure the filtering of the device
+ *
+ */
+#define HW_MAX_ADDRS 4 /* Must query to get it! */
+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;);
+
+	if (dev->flags&IFF_PROMISC) {
+		/* Enable promiscuous mode */
+		DEBUG( 0, "Promiscous mode not implemented\n");
+		/* outw(MULTICAST|PROMISC, ioaddr); */
+	}
+	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");
+		/* hardware_set_filter(NULL); */
+
+		irlan_set_multicast_filter( self, TRUE);
+	}
+	else if (dev->mc_count) {
+		DEBUG( 4, __FUNCTION__ "(), Setting multicast filter\n");
+		/* Walk the address list, and load the filter */
+		/* hardware_set_filter(dev->mc_list); */
+
+		irlan_set_multicast_filter( self, TRUE);
+	}
+	else {
+		DEBUG( 4, __FUNCTION__ "(), Clearing multicast filter\n");
+		irlan_set_multicast_filter( self, FALSE);
+	}
+
+	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);
+	}
+}
+
+/*
+ * Function irlan_get_stats (dev)
+ *
+ *    Get the current statistics for this device
+ *
+ */
+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;);
+
+	return &self->stats;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlan/irlan_event.c linux/net/irda/irlan/irlan_event.c
--- v2.1.131/linux/net/irda/irlan/irlan_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_event.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,48 @@
+/*********************************************************************
+ *                
+ * Filename:      irlan_event.c
+ * Version:       
+ * Description:   
+ * 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 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 <net/irda/irlan_event.h>
+
+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",
+};
+
+void irlan_next_state( struct irlan_cb *self, 
+		       IRLAN_STATE state) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+	self->state = state;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlan/irlan_srv.c linux/net/irda/irlan/irlan_srv.c
--- v2.1.131/linux/net/irda/irlan/irlan_srv.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_srv.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,915 @@
+/*********************************************************************
+ *                
+ * 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.1.131/linux/net/irda/irlan/irlan_srv_event.c linux/net/irda/irlan/irlan_srv_event.c
--- v2.1.131/linux/net/irda/irlan/irlan_srv_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlan/irlan_srv_event.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,268 @@
+/*********************************************************************
+ *                
+ * 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.1.131/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.1.131/linux/net/irda/irlap.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlap.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1184 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap.c
+ * Version:       0.3
+ * 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:   Mon Dec 14 11:54:42 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 iyt 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/config.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/delay.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irqueue.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irlmp_frame.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irlap.h>
+#include <net/irda/timer.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap_comp.h>
+
+hashbin_t *irlap = NULL;
+
+static void __irlap_close( struct irlap_cb *self);
+
+#ifdef CONFIG_PROC_FS
+int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
+		     int unused);
+
+#endif /* CONFIG_PROC_FS */
+
+__initfunc(int irlap_init( void))
+{
+	/* Allocate master array */
+	irlap = hashbin_new( HB_LOCAL);
+	if ( irlap == NULL) {
+		printk( KERN_WARNING "IrLAP: Can't allocate irlap hashbin!\n");
+		return -ENOMEM;
+	}
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	irlap_compressors = hashbin_new( HB_LOCAL);
+	if ( irlap_compressors == NULL) {
+		printk( KERN_WARNING "IrLAP: Can't allocate compressors hashbin!\n");
+		return -ENOMEM;
+	}
+#endif
+
+	return 0;
+}
+
+void irlap_cleanup(void)
+{
+	ASSERT( irlap != NULL, return;);
+
+	hashbin_delete( irlap, (FREE_FUNC) __irlap_close);
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	hashbin_delete( irlap_compressors, (FREE_FUNC) kfree);
+#endif
+}
+
+/*
+ * Function irlap_open (driver)
+ *
+ *    Initialize IrLAP layer
+ *
+ */
+struct irlap_cb *irlap_open( struct irda_device *irdev)
+{
+	struct irlap_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( irdev != NULL, return NULL;);
+	ASSERT( irdev->magic == IRDA_DEVICE_MAGIC, return NULL;);
+
+	/* Initialize the irlap structure. */
+	self = kmalloc( sizeof( struct irlap_cb), GFP_KERNEL);
+	if ( self == NULL)
+		return NULL;
+	
+	memset( self, 0, sizeof(struct irlap_cb));
+	self->magic = LAP_MAGIC;
+
+	/* Make a binding between the layers */
+	self->irdev = irdev;
+	self->netdev = &irdev->netdev;
+
+	irlap_next_state( self, LAP_OFFLINE);
+
+	/* Initialize transmitt queue */
+	skb_queue_head_init( &self->tx_list);
+	skb_queue_head_init( &self->wx_list);
+
+	/* My unique IrLAP device address! :-) */
+	self->saddr = jiffies;
+
+	/*  Generate random connection address for this session */
+	self->caddr = jiffies & 0xfe;
+
+	init_timer( &self->slot_timer);
+	init_timer( &self->query_timer);
+	init_timer( &self->discovery_timer);
+	init_timer( &self->final_timer);		
+	init_timer( &self->poll_timer);
+	init_timer( &self->wd_timer);
+	init_timer( &self->backoff_timer);
+
+	irlap_apply_default_connection_parameters( self);
+	
+	irlap_next_state( self, LAP_NDM);
+
+	hashbin_insert( irlap, (QUEUE *) self, self->saddr, NULL);
+
+	irlmp_register_irlap( self, self->saddr, &self->notify);
+	
+	DEBUG( 4, "irlap_open -->\n");
+
+	return self;
+}
+
+/*
+ * Function __irlap_close (self)
+ *
+ *    Remove IrLAP and all allocated memory. Stop any pending timers.
+ *
+ */
+static void __irlap_close( struct irlap_cb *self)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	/* Stop timers */
+	del_timer( &self->slot_timer);
+	del_timer( &self->query_timer);
+	del_timer( &self->discovery_timer);
+	del_timer( &self->final_timer);		
+	del_timer( &self->poll_timer);
+	del_timer( &self->wd_timer);
+	del_timer( &self->backoff_timer);
+
+	irlap_flush_all_queues( self);
+       
+	self->irdev = NULL;
+	self->magic = ~LAP_MAGIC;
+	
+	kfree( self);
+}
+
+/*
+ * Function irlap_close ()
+ *
+ *    
+ *
+ */
+void irlap_close( struct irlap_cb *self) 
+{
+	struct irlap_cb *lap;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+
+	irlmp_unregister_irlap( self->saddr);
+	self->notify.instance = NULL;
+
+	/* 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");
+		return;
+	}
+	__irlap_close( lap);
+}
+
+/*
+ * Function irlap_connect_indication ()
+ *
+ *    Another device is attempting to make a connection
+ *
+ */
+void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb) 
+{
+	DEBUG( 4, "irlap_connect_indication()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_init_qos_capabilities( self, NULL); /* No user QoS! */
+	
+	irlmp_link_connect_indication( self->notify.instance, &self->qos_tx, 
+				       skb);
+}
+
+/*
+ * Function irlap_connect_response (void)
+ *
+ *    Service user has accepted incomming connection
+ *
+ */
+void irlap_connect_response( struct irlap_cb *self, struct sk_buff *skb) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	irlap_do_event( self, CONNECT_RESPONSE, skb, NULL);
+}
+
+/*
+ * Function irlap_connect_request (daddr, qos, sniff)
+ *
+ *    Request connection with another device, sniffing is not implemented 
+ *    yet.
+ */
+void irlap_connect_request( struct irlap_cb *self, __u32 daddr, 
+			    struct qos_info *qos_user, int sniff) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	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) {
+		irlap_do_event( self, CONNECT_REQUEST, NULL, NULL);
+	} else {
+		DEBUG( 0, "irlap_connect_request() Wrong state!\n");
+		
+		irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
+	}
+	       
+}
+
+/*
+ * Function irlap_connect_confirm (void)
+ *
+ *    Connection request is accepted
+ *
+ */
+void irlap_connect_confirm( struct irlap_cb *self, struct sk_buff *skb)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlmp_link_connect_confirm( self->notify.instance, &self->qos_tx, skb);
+}
+
+/*
+ * Function irlap_data_indication (skb)
+ *
+ *    Received data frames from IR-port, so we just pass them up to 
+ *    IrLMP for further processing
+ *
+ */
+inline void irlap_data_indication( struct irlap_cb *self, struct sk_buff *skb) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	IS_SKB( skb, return;);
+
+	/* Hide LAP header from IrLMP layer */
+	skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	if ( self->qos_tx.compression.value) {
+		skb = irlap_decompress_frame( self, skb);
+		if ( !skb) {
+			DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+			return;
+		}
+	}
+#endif
+
+	irlmp_link_data_indication( self->notify.instance, LAP_RELIABLE, skb);
+}
+
+/*
+ * Function irlap_unit_data_indication (self, skb)
+ *
+ *    Received some data that was sent unreliable
+ *
+ */
+void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
+{
+	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	IS_SKB( skb, return;);
+
+	/* Hide LAP header from IrLMP layer */
+	skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	if ( self->qos_tx.compression.value) {
+		
+		skb = irlap_decompress_frame( self, skb);
+		if ( !skb) {
+			DEBUG( 0, __FUNCTION__ "(), Decompress error!\n");
+			return;
+		}
+	}
+#endif
+	
+	irlmp_link_data_indication( self->notify.instance, LAP_UNRELIABLE, 
+				    skb);
+}
+
+/*
+ * Function irlap_data_request (self, skb)
+ *
+ *    Queue data for transmission, must wait until XMIT state
+ *
+ */
+inline void irlap_data_request( struct irlap_cb *self, struct sk_buff *skb,
+				int reliable)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+       
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	IS_SKB( skb, return;);
+
+	DEBUG( 4, "irlap_data_request: 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");
+			return;
+		}
+	}
+#endif
+	
+	ASSERT( skb_headroom( skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 
+		return;);
+	skb_push( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
+
+	/*  
+	 *  Must set frame format now so that the rest of the code knows 
+	 *  if its dealing with an I or an UI frame
+	 */
+	if ( reliable)
+		skb->data[1] = I_FRAME;
+	else {
+		DEBUG( 4, __FUNCTION__ "(), queueing unreliable frame\n");
+		skb->data[1] = UI_FRAME;
+	}
+
+	IS_SKB( skb, return;);
+
+	/* 
+	 *  Send event if this frame only if we are in the right state 
+	 *  FIXME: udata should be sent first! (skb_queue_head?)
+	 */
+  	if (( self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {
+		/*
+		 *  Check if the transmit queue contains some unsent frames,
+		 *  and if so, make sure they are sent first
+		 */
+		if ( !skb_queue_empty( &self->tx_list)) {
+			skb_queue_tail( &self->tx_list, skb);
+			skb = skb_dequeue( &self->tx_list);
+			
+			ASSERT( skb != NULL, return;);
+			IS_SKB( skb, return;);
+		}
+		irlap_do_event( self, SEND_I_CMD, skb, NULL);
+	} else
+		skb_queue_tail( &self->tx_list, skb);
+	
+}
+
+/*
+ * Function irlap_disconnect_request (void)
+ *
+ *    Request to disconnect connection by service user
+ */
+void irlap_disconnect_request( struct irlap_cb *self) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_do_event( self, DISCONNECT_REQUEST, NULL, NULL);
+}
+
+/*
+ * Function irlap_disconnect_indication (void)
+ *
+ *    Disconnect request from other device
+ *
+ */
+void irlap_disconnect_indication( struct irlap_cb *self, LAP_REASON reason) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	irda_free_compression( self);
+#endif
+
+	/* Flush queues */
+	irlap_flush_all_queues( self);
+	
+	switch( reason) {
+	case LAP_RESET_INDICATION:
+		DEBUG( 0, "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_MEDIA_BUSY:
+		irlmp_link_disconnect_indication( self->notify.instance, 
+						  self, reason, NULL);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Reason %d not implemented!\n", 
+		       reason);
+	}
+}
+
+/*
+ * Function irlap_discovery_request (gen_addr_bit)
+ *
+ *    Start one single discovery operation.
+ *
+ */
+void irlap_discovery_request( struct irlap_cb *self, DISCOVERY *discovery) 
+{
+	struct irlap_info info;
+	
+	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( discovery != NULL, 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 = 0; /* Current slot */
+
+		self->discovery_cmd = discovery;
+		info.discovery = discovery;
+		
+		irlap_do_event( self, DISCOVERY_REQUEST, NULL, &info);
+	} else { 
+ 		DEBUG( 4, __FUNCTION__ 
+ 			"(), discovery only possible in NDM mode\n");
+		irlap_discovery_confirm( self, NULL);
+ 	} 
+}
+
+
+/*
+ * Function irlap_discovery_confirm (log)
+ *
+ *    A device has been discovered in front of this station, we
+ *    report directly to LMP.
+ */
+void irlap_discovery_confirm( struct irlap_cb *self, 
+			      hashbin_t *discovery_log) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	
+	ASSERT( self->notify.instance != NULL, return;);
+
+	/* Inform IrLMP */
+	irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
+
+	/* 
+	 *  IrLMP has now the responsibilities for the discovery_log 
+	 */
+	self->discovery_log = NULL;
+}
+
+/*
+ * Function irlap_discovery_indication (log)
+ *
+ *    Somebody is trying to discover us!
+ *
+ */
+inline void irlap_discovery_indication( struct irlap_cb *self, 
+					DISCOVERY *discovery) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( discovery != NULL, return;);
+
+	ASSERT( self->notify.instance != NULL, return;);
+	
+	irlmp_discovery_indication( self->notify.instance, discovery);
+}
+
+/*
+ * Function irlap_status_indication (quality_of_link)
+ *
+ *    
+ *
+ */
+void irlap_status_indication( int quality_of_link) 
+{
+	switch( quality_of_link) {
+	case STATUS_NO_ACTIVITY:
+		printk( KERN_INFO "IrLAP, no activity on link!\n");
+		break;
+	case STATUS_NOISY:
+		printk( KERN_INFO "IrLAP, noisy link!\n");
+		break;
+	default:
+		break;
+	}
+	/* TODO: layering violation! */
+	irlmp_status_indication( quality_of_link, NO_CHANGE);
+}
+
+/*
+ * Function irlap_reset_indication (void)
+ *
+ *    
+ *
+ */
+void irlap_reset_indication( struct irlap_cb *self)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	
+	irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+}
+
+/*
+ * Function irlap_reset_confirm (void)
+ *
+ *    
+ *
+ */
+void irlap_reset_confirm(void)
+{
+	DEBUG( 0, __FUNCTION__ "() Not implemented!\n");	
+}
+
+/*
+ * Function irlap_generate_rand_time_slot (S, s)
+ *
+ *    Generate a random time slot between s and S-1 where
+ *    S = Number of slots (0 -> S-1)
+ *    s = Current slot
+ */
+int irlap_generate_rand_time_slot( int S, int s) 
+{
+	int slot;
+	
+	ASSERT(( S - s) > 0, return 0;);
+
+	slot = s + jiffies % (S-s);
+	
+	DEBUG( 4, "S=%d, s=%d, rnd=%d\n", S, s, slot);
+
+	ASSERT(( slot >= s) || ( slot < S), return 0;);
+	
+	return slot;
+}
+
+/*
+ * Function irlap_update_nr_received (nr)
+ *
+ *    Remove all acknowledged frames in current window queue. This code is 
+ *    not intuitive and you should not try to change it. If you think it
+ *    contains bugs, please mail a patch to the author instead.
+ */
+void irlap_update_nr_received( struct irlap_cb *self, int nr) 
+{
+	struct sk_buff *skb = NULL;
+	int count = 0;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	/*
+         * Remove all the ack-ed frames from the window queue.
+         */
+
+	DEBUG( 4, "--> wx_list=%d, va=%d, nr=%d\n", 
+	       skb_queue_len( &self->wx_list), self->va, nr);
+
+	/* 
+	 *  Optimize for the common case. It is most likely that the receiver
+	 *  will acknowledge all the frames we have sent! So in that case we
+	 *  delete all frames stored in window.
+	 */
+	if ( nr == self->vs) {
+		while (( skb = skb_dequeue( &self->wx_list)) != NULL) {
+		     dev_kfree_skb(skb);
+		}
+		/* The last acked frame is the next to send minus one */
+		self->va = nr - 1;
+	} else {
+		/* Remove all acknowledged frames in current window */
+		while (( skb_peek( &self->wx_list) != NULL) && 
+		       ((( self->va+1) % 8) != nr)) 
+		{
+			skb = skb_dequeue( &self->wx_list);
+			dev_kfree_skb(skb);
+			
+			self->va = (self->va + 1) % 8;
+			count++;
+		}
+		
+		DEBUG( 4, "irlap_update_nr_received(), removed %d\n", count);
+		DEBUG( 4, "wx_list=%d, va=%d, nr=%d -->\n", 
+		       skb_queue_len( &self->wx_list), self->va, nr);
+	}
+	
+	/* Advance window */
+	self->window = self->window_size - skb_queue_len( &self->wx_list);
+}
+
+/*
+ * Function irlap_validate_ns_received (ns)
+ *
+ *    Validate the next to send (ns) field from received frame.
+ */
+int irlap_validate_ns_received( struct irlap_cb *self, int ns) 
+{
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+
+	/* 
+	 *  ns as expected?
+	 */
+	if ( ns == self->vr) {
+		DEBUG( 4, "*** irlap_validate_ns_received: expected!\n");
+		return NS_EXPECTED;
+	}
+	/*
+	 *  Stations are allowed to treat invalid NS as unexpected NS
+	 *  IrLAP, Recv ... with-invalid-Ns. p. 84
+	 */
+	return NS_UNEXPECTED;
+
+	/* return NR_INVALID; */
+}
+/*
+ * Function irlap_validate_nr_received (nr)
+ *
+ *    Validate the next to receive (nr) field from received frame.
+ *
+ */
+int irlap_validate_nr_received( struct irlap_cb *self, int nr) 
+{
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+
+	/* 
+	 *  nr as expected?
+	 */
+	if ( nr == self->vs) {
+		DEBUG( 4, "*** irlap_validate_nr_received: expected!\n");
+		return NR_EXPECTED;
+	}
+
+	/*
+	 *  unexpected nr? (but within current window), first we check if the 
+	 *  ns numbers of the frames in the current window wrap.
+	 */
+	if ( self->va < self->vs) {
+		if (( nr >= self->va) && ( nr <= self->vs)) {
+			DEBUG( 4, "*** irlap_validate_nr_received:"
+			       " unexpected nr, no wrap\n");
+			return NR_UNEXPECTED;
+		}
+	} else {
+		if (( nr >= self->va) || ( nr <= self->vs)) {
+			DEBUG( 4, "*** irlap_validate_nr_received:"
+			       " unexpected nr, wrapped\n");
+			return NR_UNEXPECTED;
+		}
+	}	
+
+	/* Invalid nr!  */
+	DEBUG( 4, "irlap_validate_nr_received: invalid nr!, "
+	       " vs=%d, vr=%d, va=%d, nr=%d\n",
+	       self->vs, self->vr, self->va, nr);
+
+	return NR_INVALID;
+}
+
+/*
+ * Function irlap_initiate_connection_state ()
+ *
+ *    Initialize the connection state parameters
+ *
+ */
+void irlap_initiate_connection_state( struct irlap_cb *self) 
+{
+	DEBUG( 4, "irlap_initiate_connection_state()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	/*
+	 * Next to send and next to receive
+	 */
+	self->vs = self->vr = 0;
+
+	/* Last frame which got acked (0 - 1) % 8 */
+	self->va = 7;
+
+	self->window = 1;
+
+	self->remote_busy = FALSE;
+	self->retry_count = 0;
+}
+
+/*
+ * Function irlap_wait_min_turn_around (self, qos)
+ *
+ *    Wait negotiated minimum turn around time, this function actually sets
+ *    the number of BOS's that must be sent before the next transmitted
+ *    frame in order to delay for the specified amount of time. This is
+ *    done to avoid using timers, and the forbidden udelay!
+ */
+void irlap_wait_min_turn_around( struct irlap_cb *self, struct qos_info *qos) 
+{
+	int usecs;
+	int speed;
+	int bytes = 0;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( qos != NULL, return;);
+
+	/*
+	 *  Get QoS values.
+	 */
+	speed = qos->baud_rate.value;
+	usecs = qos->min_turn_time.value;
+
+	/* No need to calculate XBOFs for speeds over 115200 bps */
+	if ( speed > 115200) {
+		self->mtt_required = usecs;
+		return;
+	}
+	
+	DEBUG( 4, __FUNCTION__ "(), delay=%d usecs\n", usecs); 
+	
+	/*  
+	 *  Send additional BOF's for the next frame for the requested
+	 *  min turn time, so now we must calculate how many chars (XBOF's) we 
+	 *  must send for the requested time period (min turn time)
+	 */
+	bytes = speed * usecs / 10000000;
+
+	DEBUG( 4, __FUNCTION__ "(), xbofs delay = %d\n", bytes);
+	
+	self->xbofs_delay = bytes;
+}
+
+/*
+ * Function irlap_flush_all_queues (void)
+ *
+ *    Flush all queues
+ *
+ */
+void irlap_flush_all_queues( struct irlap_cb *self) 
+{
+	struct sk_buff* skb;
+
+	DEBUG( 4, "irlap_flush_all_queues()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	/*
+	 *  Free transmission queue
+	 */
+	while (( skb = skb_dequeue( &self->tx_list)) != NULL) {
+		dev_kfree_skb( skb);
+	}
+	
+	/*
+	 *  Free sliding window buffered packets
+	 */
+	while (( skb = skb_dequeue( &self->wx_list)) != NULL) {
+		dev_kfree_skb( skb);
+	}
+}
+
+/*
+ * Function irlap_setspeed (self, speed)
+ *
+ *    Change the speed of the IrDA port
+ *
+ */
+void irlap_change_speed( struct irlap_cb *self, int speed)
+{
+	DEBUG( 4, __FUNCTION__ "(), setting speed to %d\n", speed);
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	if ( !self->irdev) {
+		DEBUG( 0, __FUNCTION__ "(), driver missing!\n");
+		return;
+	}
+
+	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)
+{
+	struct irda_compressor *comp;
+	__u8 mask; /* Current bit tested */
+	int i;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	/* 
+	 *  Find out which compressors we support. We do this be checking that
+	 *  the corresponding compressor for each bit set in the QoS bits has 
+	 *  actually been loaded. Ths is sort of hairy code but that is what 
+	 *  you get when you do a little bit flicking :-)
+	 */
+	DEBUG( 4, __FUNCTION__ "(), comp bits 0x%02x\n", 
+	       self->qos_rx.compression.bits); 
+	mask = 0x80; /* Start with testing MSB */
+	for ( i=0;i<8;i++) {
+		DEBUG( 4, __FUNCTION__ "(), testing bit %d\n", 8-i);
+		if ( self->qos_rx.compression.bits & mask) {
+			DEBUG( 4, __FUNCTION__ "(), bit %d is set by defalt\n",
+			       8-i);
+			comp = hashbin_find( irlap_compressors, 
+					     compression[ msb_index(mask)], 
+					     NULL);
+			if ( !comp) {
+				/* Protocol not supported, so clear the bit */
+				DEBUG( 4, __FUNCTION__ "(), Compression "
+				       "protocol %d has not been loaded!\n", 
+				       compression[msb_index(mask)]);
+				self->qos_rx.compression.bits &= ~mask;
+				DEBUG( 4, __FUNCTION__ 
+				       "(), comp bits 0x%02x\n", 
+				       self->qos_rx.compression.bits); 
+			}
+		}
+		/* Try the next bit */
+		mask >>= 1;
+	}
+}
+#endif	
+
+/*
+ * Function irlap_init_qos_capabilities (self, qos)
+ *
+ *    Initialize QoS for this IrLAP session, What we do is to compute the
+ *    intersection of the QoS capabilities for the user, driver and for
+ *    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)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( self->irdev != NULL, return;);
+
+	/* Start out with the maximum QoS support possible */
+	irda_init_max_qos_capabilies( &self->qos_rx);
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	irlap_init_comp_qos_capabilities( self);
+#endif
+
+	/* Apply drivers QoS capabilities */
+	irda_qos_compute_intersection( &self->qos_rx, 
+				       irda_device_get_qos( self->irdev));
+
+	/*
+	 *  Check for user supplied QoS parameters. The service user is only 
+	 *  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->baud_rate.bits)
+			self->qos_rx.baud_rate.bits &= qos_user->baud_rate.bits;
+
+		if ( qos_user->max_turn_time.bits)
+			self->qos_rx.max_turn_time.bits &= qos_user->max_turn_time.bits;
+		if ( qos_user->data_size.bits)
+			self->qos_rx.data_size.bits &= qos_user->data_size.bits;
+
+		if ( qos_user->link_disc_time.bits)
+			self->qos_rx.link_disc_time.bits &= qos_user->link_disc_time.bits;
+#ifdef CONFIG_IRDA_COMPRESSION
+		self->qos_rx.compression.bits &= qos_user->compression.bits;
+#endif
+	}
+
+	/* 
+	 *  Make the intersection between IrLAP and drivers QoS
+	 *  capabilities 
+	 */
+
+	/* Use 500ms in IrLAP for now */
+	self->qos_rx.max_turn_time.bits &= 0x03;
+
+	/* Set data size */
+	/* self->qos_rx.data_size.bits &= 0x03; */
+
+	irda_qos_bits_to_value( &self->qos_rx);
+}
+
+/*
+ * Function irlap_apply_default_connection_parameters (void)
+ *
+ *    Use the default connection and transmission parameters
+ * 
+ */
+void irlap_apply_default_connection_parameters( struct irlap_cb *self)
+{
+	DEBUG( 4, "irlap_apply_default_connection_parameters()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_change_speed( self, 9600);
+
+	/* Default value in NDM */
+	self->bofs_count = 11;
+
+	/* Use these until connection has been made */
+	self->final_timeout = FINAL_TIMEOUT;
+	self->poll_timeout = POLL_TIMEOUT;
+	self->wd_timeout = WD_TIMEOUT;
+
+	self->qos_tx.data_size.value = 64;
+	self->qos_tx.additional_bofs.value = 11;
+
+	irlap_flush_all_queues( self);
+}
+
+/*
+ * Function irlap_apply_connection_parameters (qos)
+ *
+ *    Initialize IrLAP with the negotiated QoS values
+ *
+ */
+void irlap_apply_connection_parameters( struct irlap_cb *self, 
+					struct qos_info *qos) 
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_change_speed( self, qos->baud_rate.value);
+
+	self->window_size = qos->window_size.value;
+	self->window      = qos->window_size.value;
+	self->bofs_count  = qos->additional_bofs.value;
+
+	/*
+	 *  Calculate how many bytes it is possible to transmit before the
+	 *  link must be turned around wb = baud * mtt/1000 * 1/2
+	 */
+	self->window_bytes = qos->baud_rate.value 
+		* qos->max_turn_time.value / 10000;
+	DEBUG( 4, "Setting window_bytes = %d\n", self->window_bytes);
+
+	/*
+	 *  Set N1 to 0 if Link Disconnect/Threshold Time = 3 and set it to 
+	 *  3 seconds otherwise. See page 71 in IrLAP for more details.
+	 *  TODO: these values should be calculated from the final timer
+         *  as well
+	 */
+	if ( qos->link_disc_time.value == 3)
+		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);
+
+	/* 
+	 *  Initialize timeout values, some of the rules are listed on 
+	 *  page 92 in IrLAP. Divide by 10 since the kernel timers has a
+	 *  resolution of 10 ms.
+	 */
+	self->poll_timeout = qos->max_turn_time.value / 10;
+	self->final_timeout = qos->max_turn_time.value / 10;
+	self->wd_timeout = self->poll_timeout * 2;
+
+	DEBUG( 4, __FUNCTION__ "(), Setting poll timeout = %d\n", 
+	       self->poll_timeout);
+	DEBUG( 4, __FUNCTION__ "(), Setting final timeout = %d\n", 
+	       self->final_timeout);
+	DEBUG( 4, __FUNCTION__ "(), Setting wd timeout = %d\n", 
+	       self->wd_timeout);
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	if ( qos->compression.value) {
+		DEBUG( 0, __FUNCTION__ "(), Initializing compression\n");
+		irda_set_compression( self, qos->compression.value);
+
+		irlap_compressor_init( self, 0);
+	}
+#endif
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irlap_proc_read (buf, start, offset, len, unused)
+ *
+ *    Give some info to the /proc file system
+ *
+ */
+int irlap_proc_read( char *buf, char **start, off_t offset, int len, 
+		     int unused)
+{
+	struct irlap_cb *self;
+	unsigned long flags;
+	int i = 0;
+     
+	save_flags(flags);
+	cli();
+
+	len = 0;
+
+	self = (struct irlap_cb *) hashbin_get_first( irlap);
+	while ( self != NULL) {
+		ASSERT( self != NULL, return -ENODEV;);
+		ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+
+		len += sprintf( buf+len, "IrLAP[%d] <-> %s ",
+				i++, self->irdev->name);
+		len += sprintf( buf+len, "state: %s\n", 
+				irlap_state[ self->state]);
+		
+		len += sprintf( buf+len, "  caddr: %#02x, ", self->caddr);
+		len += sprintf( buf+len, "saddr: %#08x, ", self->saddr);
+		len += sprintf( buf+len, "daddr: %#08x\n", self->daddr);
+		
+		len += sprintf( buf+len, "  win size: %d, ", 
+				self->window_size);
+		len += sprintf( buf+len, "win: %d, ", self->window);
+		len += sprintf( buf+len, "win bytes: %d, ", self->window_bytes);
+		len += sprintf( buf+len, "bytes left: %d\n", self->bytes_left);
+
+		len += sprintf( buf+len, "  tx queue len: %d ", 
+				skb_queue_len( &self->tx_list));
+		len += sprintf( buf+len, "win queue len: %d ", 
+				skb_queue_len( &self->wx_list));
+		len += sprintf( buf+len, "rbusy: %s\n", self->remote_busy ? 
+				"TRUE" : "FALSE");
+		
+		len += sprintf( buf+len, "  retrans: %d ", self->retry_count);
+		len += sprintf( buf+len, "vs: %d ", self->vs);
+		len += sprintf( buf+len, "vr: %d ", self->vr);
+		len += sprintf( buf+len, "va: %d\n", self->va);
+		
+		len += sprintf( buf+len, "  qos\tbps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\tcomp\n");
+		
+		len += sprintf( buf+len, "  tx\t%d\t", 
+				self->qos_tx.baud_rate.value);
+		len += sprintf( buf+len, "%d\t", 
+				self->qos_tx.max_turn_time.value);
+		len += sprintf( buf+len, "%d\t",
+				self->qos_tx.data_size.value);
+		len += sprintf( buf+len, "%d\t",
+				self->qos_tx.window_size.value);
+		len += sprintf( buf+len, "%d\t",
+				self->qos_tx.additional_bofs.value);
+		len += sprintf( buf+len, "%d\t", 
+				self->qos_tx.min_turn_time.value);
+		len += sprintf( buf+len, "%d\t", 
+				self->qos_tx.link_disc_time.value);
+#ifdef CONFIG_IRDA_COMPRESSION
+		len += sprintf( buf+len, "%d",
+				self->qos_tx.compression.value);
+#endif
+		len += sprintf( buf+len, "\n");
+
+		len += sprintf( buf+len, "  rx\t%d\t", 
+				self->qos_rx.baud_rate.value);
+		len += sprintf( buf+len, "%d\t", 
+				self->qos_rx.max_turn_time.value);
+		len += sprintf( buf+len, "%d\t",
+				self->qos_rx.data_size.value);
+		len += sprintf( buf+len, "%d\t",
+				self->qos_rx.window_size.value);
+		len += sprintf( buf+len, "%d\t",
+				self->qos_rx.additional_bofs.value);
+		len += sprintf( buf+len, "%d\t", 
+				self->qos_rx.min_turn_time.value);
+		len += sprintf( buf+len, "%d\t", 
+				self->qos_rx.link_disc_time.value);
+#ifdef CONFIG_IRDA_COMPRESSION
+		len += sprintf( buf+len, "%d",
+				self->qos_rx.compression.value);
+#endif
+		len += sprintf( buf+len, "\n");
+		
+		self = (struct irlap_cb *) hashbin_get_next( irlap);
+	}
+	restore_flags(flags);
+
+	return len;
+}
+
+#endif /* CONFIG_PROC_FS */
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlap_comp.c linux/net/irda/irlap_comp.c
--- v2.1.131/linux/net/irda/irlap_comp.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlap_comp.c	Fri Dec 18 08:06:39 1998
@@ -0,0 +1,351 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap_comp.c
+ * Version:       
+ * Description:   
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * Sources:       ppp.c, isdn_ppp.c
+ * 
+ *     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 <net/irda/irda.h>
+#include <net/irda/irqueue.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlap_comp.h>
+#include "../../drivers/net/zlib.h"
+
+hashbin_t *irlap_compressors = NULL;
+
+/*
+ * Function irda_register_compressor (cp)
+ *
+ *    Register new compressor with the IrLAP
+ *
+ */
+int irda_register_compressor( struct compressor *cp)
+{
+	struct irda_compressor *new;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Check if this compressor has been registred before */
+	if ( hashbin_find ( irlap_compressors, cp->compress_proto, NULL)) {
+		DEBUG( 0, __FUNCTION__ "(), Compressor already registered\n");
+                return 0;
+        }
+	
+	/* Make new IrDA compressor */
+        new = (struct irda_compressor *) 
+		kmalloc( sizeof( struct irda_compressor), GFP_KERNEL);
+        if (new == NULL)
+                return 1;
+		
+	memset( new, 0, sizeof( struct irda_compressor));
+        new->cp = cp;
+
+	/* Insert IrDA compressor into hashbin */
+	hashbin_insert( irlap_compressors, (QUEUE *) new, cp->compress_proto,
+			NULL);
+	
+        return 0;
+}
+
+/*
+ * Function irda_unregister_compressor (cp)
+ *
+ *    Unregister compressor
+ *
+ */
+void irda_unregister_compressor ( struct compressor *cp)
+{
+	struct irda_compressor *node;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	node = hashbin_remove( irlap_compressors, cp->compress_proto, NULL);
+	if ( !node) {
+		DEBUG( 0, __FUNCTION__ "(), compressor not found!\n");
+		return;
+	}
+	
+	kfree( node);
+}
+
+/*
+ * Function irda_set_compression (self, proto)
+ *
+ *    The the compression protocol to be used by this session
+ *
+ */
+int irda_set_compression( struct irlap_cb *self, int proto)
+{
+	struct compressor *cp;
+	struct irda_compressor *comp;
+
+	__u8 options[CILEN_DEFLATE];
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+
+	/* Initialize options */
+	options[0] = CI_DEFLATE;
+	options[1] = CILEN_DEFLATE;
+	options[2] = DEFLATE_METHOD( DEFLATE_METHOD_VAL);
+	options[3] = DEFLATE_CHK_SEQUENCE;
+
+	comp = hashbin_find( irlap_compressors, proto, NULL);
+	if ( !comp) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to find compressor\n");
+		return -1;
+	}
+
+	cp = comp->cp;
+	/* 
+	 *  Compressor part
+	 */
+	if ( self->compressor.state != NULL)
+		(*self->compressor.cp->comp_free)( self->compressor.state);
+	self->compressor.state = NULL;
+	
+	self->compressor.cp = cp;
+	self->compressor.state = cp->comp_alloc( options, sizeof( options));
+	if ( self->compressor.state == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Failed!\n");
+		return -ENOBUFS;
+	}
+
+	/* 
+	 *  Decompress part
+	 */
+	
+	if ( self->decompressor.state != NULL)
+		irda_decomp_free( self->decompressor.state);
+	self->decompressor.state = NULL;
+	
+	self->decompressor.cp = cp;
+	self->decompressor.state = cp->decomp_alloc( options, sizeof( options));
+	if ( self->decompressor.state == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), Failed!\n");
+		return -ENOBUFS;
+	}
+	return 0;
+}
+
+/*
+ * Function irda_free_compression (self)
+ *
+ *    
+ *
+ */
+void irda_free_compression( struct irlap_cb *self)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	if ( self->compressor.state) {
+		irda_comp_free( self->compressor.state);
+		self->compressor.state = NULL;
+	}
+	
+	if ( self->decompressor.state) {
+		irda_decomp_free( self->decompressor.state);
+		self->decompressor.state = NULL;
+	}
+}
+
+/*
+ * Function irlap_compress_init (self)
+ *
+ *    
+ *
+ */
+void irlap_compressor_init( struct irlap_cb *self, int compress)
+{
+	int debug = TRUE;
+	__u8 options[CILEN_DEFLATE];
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	
+	/* Initialize options */
+	options[0] = CI_DEFLATE;
+	options[1] = CILEN_DEFLATE;
+	options[2] = DEFLATE_METHOD_VAL;
+	options[3] = DEFLATE_CHK_SEQUENCE;
+	
+	/*
+	 *  We're agreeing to send compressed packets.
+	 */
+	if ( self->compressor.state == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
+		return;
+	}
+	
+	if ((*self->compressor.cp->comp_init)( self->compressor.state, 
+					       options, sizeof( options),
+					       0, 0, debug)) 
+	{
+		DEBUG( 0, __FUNCTION__ "(), Compressor running!\n");
+		/* ppp->flags |= SC_COMP_RUN; */
+	}
+	
+	/*
+	 *  Initialize decompressor
+	 */
+	if ( self->decompressor.state == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), state == NULL\n");
+		return;
+	}
+	
+	if (( self->decompressor.cp->decomp_init)( self->decompressor.state,
+						   options, sizeof( options),
+						   0, 0, 0, debug)) 
+	{
+		DEBUG( 0, __FUNCTION__ "(), Decompressor running!\n");	
+		
+		/* ppp->flags |= SC_DECOMP_RUN; */
+		/* ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR); */
+	}
+}
+
+/*
+ * Function irlap_compress_frame (self, skb)
+ *
+ *
+ *
+ */
+struct sk_buff *irlap_compress_frame( struct irlap_cb *self, 
+				      struct sk_buff *skb)
+{
+	struct sk_buff *new_skb;
+	int count;
+	
+	ASSERT( skb != NULL, return NULL;);
+	
+	DEBUG( 0, __FUNCTION__ "() skb->len=%d, jiffies=%ld\n", (int) skb->len,
+	       jiffies);
+
+	ASSERT( self != NULL, return NULL;);
+	ASSERT( self->magic == LAP_MAGIC, return NULL;);
+
+	/* Check if compressor got initialized */
+	if ( self->compressor.state == NULL) {
+		/* Tell peer that this frame is not compressed */
+		skb_push( skb, LAP_COMP_HEADER);
+		skb->data[0] = IRDA_NORMAL;
+
+		return skb;
+	}
+
+	/* FIXME: Find out what is the max overhead (not 10) */
+	new_skb = dev_alloc_skb( skb->len+LAP_HEADER+10);
+	if(!new_skb)
+		return skb;
+
+	skb_reserve( new_skb, LAP_HEADER);
+	skb_put( new_skb, skb->len+10);
+	
+	count = (self->compressor.cp->compress)( self->compressor.state, 
+						 skb->data, new_skb->data, 
+						 skb->len, new_skb->len);
+	if( count <= 0) {
+		DEBUG( 0, __FUNCTION__ "(), Unable to compress frame!\n");
+		dev_kfree_skb( new_skb);
+
+		/* Tell peer that this frame is not compressed */
+		skb_push( skb, 1);
+		skb->data[0] = IRDA_NORMAL;
+
+		return skb;
+	}
+	skb_trim( new_skb, count);
+
+	/* Tell peer that this frame is compressed */
+	skb_push( new_skb, 1);
+	new_skb->data[0] = IRDA_COMPRESSED;
+
+	dev_kfree_skb( skb);
+	
+	DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n, jiffies=%ld", 
+	       (int) new_skb->len, jiffies);
+	
+	return new_skb;
+}
+
+/*
+ * Function irlap_decompress_frame (self, skb)
+ *
+ *    
+ *
+ */
+struct sk_buff *irlap_decompress_frame( struct irlap_cb *self, 
+					struct sk_buff *skb)
+{
+	struct sk_buff *new_skb;
+	int count;
+
+	DEBUG( 4, __FUNCTION__ "() skb->len=%d\n", (int) skb->len);
+
+	ASSERT( self != NULL, return NULL;);
+	ASSERT( self->magic == LAP_MAGIC, return NULL;);
+
+	ASSERT( self->compressor.state != NULL, return NULL;);
+
+	/* Check if frame is compressed */
+	if ( skb->data[0] == IRDA_NORMAL) {
+
+		/* Remove compression header */
+		skb_pull( skb, LAP_COMP_HEADER);
+
+		/*
+		 * The frame is not compressed. Pass it to the
+		 * decompression code so it can update its
+		 * dictionary if necessary.
+		 */
+		irda_incomp( self->decompressor.state, skb->data, skb->len);
+
+		return skb;
+	}
+
+	/* Remove compression header */
+	skb_pull( skb, LAP_COMP_HEADER);
+
+	new_skb = dev_alloc_skb( 2048); /* FIXME: find the right size */
+	if(!new_skb)
+		return skb;
+	skb_put( new_skb, 2048);
+
+	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");
+		
+		dev_kfree_skb( new_skb);
+		return skb;
+	}
+
+	skb_trim( new_skb, count);
+	
+	DEBUG( 0, __FUNCTION__ "() new_skb->len=%d\n", (int) new_skb->len);
+
+	return new_skb;
+}
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.1.131/linux/net/irda/irlap_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlap_event.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1831 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap_event.c
+ * Version:       0.1
+ * Description:   IrLAP state machine implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sat Aug 16 00:59:29 1997
+ * Modified at:   Mon Dec 14 14:16:00 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
+ *                        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.
+ *
+ *     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/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlap_event.h>
+
+#include <net/irda/timer.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/qos.h>
+
+#include <net/irda/irda_device.h>
+
+static int irlap_state_ndm    ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_query  ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_reply  ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_conn   ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_setup  ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_xmit_p ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_pclose ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_nrm_p  ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_reset_wait(struct irlap_cb *self, IRLAP_EVENT event, 
+				  struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_reset  ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_nrm_s  ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_xmit_s ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_sclose ( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info);
+
+static char *irlap_event[] = {
+	"DISCOVERY_REQUEST",
+	"CONNECT_REQUEST",
+	"CONNECT_RESPONSE",
+	"DISCONNECT_REQUEST",
+	"DATA_REQUEST",
+	"RESET_REQUEST",
+	"SEND_I_CMD",
+	"RECV_DISCOVERY_XID_CMD",
+	"RECV_DISCOVERY_XID_RSP",
+	"RECV_SNRM_CMD",
+	"RECV_TEST_CMD",
+	"RECV_UA_RSP",
+	"RECV_DM_RSP",
+	"RECV_I_CMD",
+	"RECV_I_RSP",
+	"RECV_UI_FRAME",
+	"RECV_FRMR_RSP",
+	"RECV_RR_CMD",
+	"RECV_RR_RSP",
+	"RECV_RNR_FRAME",
+	"RECV_DISC_FRAME",
+	"SLOT_TIMER_EXPIRED",
+	"QUERY_TIMER_EXPIRED",
+	"FINAL_TIMER_EXPIRED",
+	"POLL_TIMER_EXPIRED",
+	"DISCOVERY_TIMER_EXPIRED",
+	"WD_TIMER_EXPIRED",
+	"BACKOFF_TIMER_EXPIRED",
+};
+
+char *irlap_state[] = {
+	"LAP_NDM",
+	"LAP_QUERY",
+	"LAP_REPLY",
+	"LAP_CONN",
+	"LAP_SETUP",
+	"LAP_OFFLINE",
+	"LAP_XMIT_P",
+	"LAP_PCLOSE",
+	"LAP_NRM_P",
+	"LAP_RESET_WAIT",
+	"LAP_RESET",
+	"LAP_NRM_S",
+	"LAP_XMIT_S",
+	"LAP_SCLOSE",
+};
+
+static int (*state[])( struct irlap_cb *self, IRLAP_EVENT event, 
+		       struct sk_buff *skb, struct irlap_info *info) = 
+{ 
+	irlap_state_ndm,
+	irlap_state_query,
+	irlap_state_reply,
+	irlap_state_conn,
+	irlap_state_setup,
+	irlap_state_offline,
+	irlap_state_xmit_p,
+	irlap_state_pclose,
+	irlap_state_nrm_p,
+	irlap_state_reset_wait,
+	irlap_state_reset,
+	irlap_state_nrm_s,
+	irlap_state_xmit_s,
+	irlap_state_sclose,
+};
+
+/*
+ * Function irda_poll_timer_expired (data)
+ *
+ *    
+ *
+ */
+static void irlap_poll_timer_expired( unsigned long data)
+{
+	struct irlap_cb *self = (struct irlap_cb *) data;
+	
+	DEBUG( 4, "Poll timer expired!\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	
+	irlap_do_event( self, POLL_TIMER_EXPIRED, NULL, NULL);
+}
+
+void irlap_start_poll_timer( struct irlap_cb *self, int timeout)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+#ifdef CONFIG_IRDA_FAST_RR
+	if ( skb_queue_len( &self->tx_list) == 0) {
+		if ( self->fast_RR == TRUE) {
+			/*
+			 *  Assert that the fast poll timer has not reached the
+			 *  normal poll timer yet
+			 */
+			if ( self->fast_RR_timeout < timeout) {
+				/*
+				 *  FIXME: this should be a more configurable
+				 *         function
+				 */
+				self->fast_RR_timeout += 15;
+
+				/* Use this fast(er) timeout instead */
+				timeout = self->fast_RR_timeout;
+			}
+		} else {
+			self->fast_RR = TRUE;
+
+			/* Start with just 1 ms */
+			self->fast_RR_timeout = 1;
+			timeout = 1;
+		}
+	} else
+		self->fast_RR = FALSE;
+
+	DEBUG( 4, __FUNCTION__ "(), Timeout=%d\n", timeout);
+#endif
+	irda_start_timer( &self->poll_timer, timeout, 
+			  (unsigned long) self, irlap_poll_timer_expired);
+}
+
+/*
+ * Function irlap_do_event (event, skb, info)
+ *
+ *    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");
+		return;
+	}
+		
+  	DEBUG( 4, "irlap_do_event: 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.  
+	 */
+	while (( self->state == LAP_XMIT_P) || ( self->state == LAP_XMIT_S)) { 
+		if ( skb_queue_len( &self->tx_list) > 0) {
+			
+			struct sk_buff *skb = skb_dequeue( &self->tx_list); 
+			ASSERT( skb != NULL, return;);
+			
+			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;
+		}
+	}
+}
+
+/*
+ * Function irlap_next_state (self, state)
+ *
+ *    Switches state and provides debug information
+ *
+ */
+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");
+		return;
+	}
+	
+	DEBUG( 4, "next LAP state = %s\n", irlap_state[ state]);
+
+	self->state = state;
+
+	/*
+	 *  If we are swithing away from a XMIT state then we are allowed to 
+	 *  transmit a maximum number of bytes again when we enter the XMIT 
+	 *  state again. Since its possible to "switch" from XMIT to XMIT and
+	 *  we cannot do this when swithing into the XMIT state :-)
+	 */
+	if (( state != LAP_XMIT_P) && ( state != LAP_XMIT_S))
+		self->bytes_left = self->window_bytes;
+}
+
+/*
+ * Function irlap_state_ndm (event, skb, frame)
+ *
+ *    NDM (Normal Disconnected Mode) state
+ *
+ */
+static int irlap_state_ndm( struct irlap_cb *self, IRLAP_EVENT event, 
+			    struct sk_buff *skb,  struct irlap_info *info) 
+{
+	DISCOVERY *discovery_rsp;
+	int ret = 0;
+	
+	DEBUG( 4, "irlap_state_ndm()\n");
+	
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case CONNECT_REQUEST:
+		ASSERT( self->irdev != NULL, return -1;);
+
+		if ( irda_device_is_media_busy( self->irdev)) {
+			DEBUG( 0, __FUNCTION__
+			      "(), CONNECT_REQUEST: media busy!\n");
+			
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+			
+			irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
+		} else {
+			irlap_send_snrm_frame( self, &self->qos_rx);
+			
+			/* Start Final-bit timer */
+			irlap_start_final_timer( self, self->final_timeout);
+
+			self->retry_count = 0;
+			irlap_next_state( self, LAP_SETUP);
+		}
+		break;
+
+	case RECV_SNRM_CMD:
+		self->daddr = info->daddr;
+		self->caddr = info->caddr;
+		
+		irlap_next_state( self, LAP_CONN);
+
+		irlap_connect_indication( self, skb);
+		break;
+
+	case DISCOVERY_REQUEST:		
+		ASSERT( info != NULL, return -1;);
+
+	 	if ( irda_device_is_media_busy( self->irdev)) {
+ 			DEBUG(0, "irlap_discovery_request: media busy!\n"); 
+			/* irlap->log.condition = MEDIA_BUSY; */
+			
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM); 
+			
+			/* This will make IrLMP try again */
+ 			irlap_discovery_confirm( self, NULL);
+			return 0;
+	 	} 
+		
+		self->S = info->S;
+		self->s = info->s;
+		irlap_send_discovery_xid_frame( self, info->S, info->s, TRUE,
+						info->discovery);
+		self->s++;
+
+		irlap_start_slot_timer( self, SLOT_TIMEOUT);
+		irlap_next_state( self, LAP_QUERY);
+		break;
+
+	case RECV_DISCOVERY_XID_CMD:
+		ASSERT( info != NULL, return -1;);
+
+		/* Assert that this is not the final slot */
+		if ( info->s <= info->S) {
+			self->daddr = info->daddr; 
+			self->slot = irlap_generate_rand_time_slot( info->S,
+								    info->s);
+			DEBUG( 4, "XID_CMD: S=%d, s=%d, slot %d\n", info->S, 
+			       info->s, self->slot);
+
+			if ( self->slot == info->s) {
+				discovery_rsp = irlmp_get_discovery_response();
+				
+				DEBUG( 4, "Sending XID rsp 1\n");
+				irlap_send_discovery_xid_frame( self, info->S, 
+								self->slot, 
+								FALSE,
+								discovery_rsp);
+				self->frame_sent = TRUE;
+			} else
+				self->frame_sent = FALSE;
+			
+			irlap_start_query_timer( self, QUERY_TIMEOUT);
+			irlap_next_state( self, LAP_REPLY);
+		}
+
+		dev_kfree_skb( skb);
+		break;
+		
+	default:
+		/* 	DEBUG( 0, "irlap_state_ndm: Unknown event"); */
+		ret = -1;
+		break;
+	}	
+	return ret;
+}
+
+/*
+ * Function irlap_state_query (event, skb, info)
+ *
+ *    QUERY state
+ *
+ */
+static int irlap_state_query( struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case RECV_DISCOVERY_XID_RSP:
+		ASSERT( info != NULL, return -1;);
+		ASSERT( info->discovery != NULL, return -1;);
+
+		DEBUG( 4, "irlap_state_query(), daddr=%08x\n", 
+		       info->discovery->daddr);
+
+		hashbin_insert( self->discovery_log, 
+				(QUEUE *) info->discovery,
+				info->discovery->daddr, NULL);
+
+		dev_kfree_skb( skb);
+
+		/* Keep state */
+		irlap_next_state( self, LAP_QUERY); 
+		break;
+	case SLOT_TIMER_EXPIRED:
+		if ( self->s < self->S) {
+			irlap_send_discovery_xid_frame( self, self->S, 
+							self->s, TRUE,
+							self->discovery_cmd);
+			self->s++;
+			irlap_start_slot_timer( self, SLOT_TIMEOUT);
+			
+			/* Keep state */
+			irlap_next_state( self, LAP_QUERY);
+		} else {
+			/* This is the final slot! */
+			irlap_send_discovery_xid_frame( self, self->S, 0xff, 
+							TRUE,
+							self->discovery_cmd);
+
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+	
+			/*
+			 *  We are now finished with the discovery procedure, 
+			 *  so now we must return the results
+			 */
+			irlap_discovery_confirm( self, self->discovery_log);
+		}
+		break;
+	default:
+		DEBUG( 4, "irlap_state_query: Unknown event %d, %s\n", event, 
+		       irlap_event[event]);
+
+		if ( skb != NULL) {
+			dev_kfree_skb( skb);
+		}
+		ret = -1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_reply (self, event, skb, info)
+ *
+ *    REPLY, we have received a XID discovery frame from a device and we
+ *    are waiting for the right time slot to send a response XID frame
+ * 
+ */
+static int irlap_state_reply( struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
+{
+	DISCOVERY *discovery_rsp;
+	int ret=0;
+
+	DEBUG( 4, "irlap_state_reply()\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case QUERY_TIMER_EXPIRED:
+		DEBUG( 0, "irlap_state_reply: QUERY_TIMER_EXPIRED <%ld>\n",
+		       jiffies);
+		irlap_next_state( self, LAP_NDM);
+		break;
+	case RECV_DISCOVERY_XID_CMD:
+		ASSERT( info != NULL, return -1;);
+		/*
+		 *  Last frame?
+		 */
+		if ( info->s == 0xff) {
+			del_timer( &self->query_timer);
+			
+			/* info->log.condition = REMOTE; */
+
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+
+			irlap_discovery_indication( self, info->discovery); 
+		} else if (( info->s >= self->slot) && 
+			   ( !self->frame_sent)) {
+			DEBUG( 4, "Sending XID rsp 2, s=%d\n", info->s); 
+			discovery_rsp = irlmp_get_discovery_response();
+
+			irlap_send_discovery_xid_frame( self, info->S, 
+							self->slot, FALSE,
+							discovery_rsp);
+
+			self->frame_sent = TRUE;
+			irlap_next_state( self, LAP_REPLY);
+		}
+		dev_kfree_skb( skb);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event,
+		       irlap_event[event]);
+
+		if ( skb != NULL)
+			dev_kfree_skb( skb);
+
+		ret = -1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_conn (event, skb, info)
+ *
+ *    CONN, we have received a SNRM command and is waiting for the upper
+ *    layer to accept or refuse connection 
+ *
+ */
+static int irlap_state_conn( struct irlap_cb *self, IRLAP_EVENT event, 
+			     struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+
+	DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case CONNECT_RESPONSE:
+		skb_pull( skb, 11);
+
+		ASSERT( self->irdev != NULL, return -1;);
+		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+
+		irlap_initiate_connection_state( self);
+
+		/*
+		 * We are allowed to send two frames!
+		 */
+		irlap_send_ua_response_frame( self, &self->qos_rx);
+		irlap_send_ua_response_frame( self, &self->qos_rx);
+		
+		irlap_apply_connection_parameters( self, &self->qos_tx);
+
+		/*
+		 *  The WD-timer could be set to the duration of the P-timer 
+		 *  for this case, but it is recommomended to use twice the 
+		 *  value (note 3 IrLAP p. 60). 
+		 */
+		irlap_start_wd_timer( self, self->wd_timeout);
+		irlap_next_state( self, LAP_NRM_S);
+		break;
+
+	case RECV_SNRM_CMD:
+		DEBUG( 3, "irlap_state_conn: event RECV_SNRM_CMD!\n");
+#if 0
+		irlap_next_state( self, LAP_NDM);
+#endif
+		break;
+
+	case RECV_DISCOVERY_XID_CMD:
+		DEBUG( 3, "irlap_state_conn: 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, "irlap_state_conn: Unknown event %d, %s\n", event, 
+		       irlap_event[event]);
+		ret = -1;
+		break;
+	}
+	
+	return ret;
+}
+
+/*
+ * Function irlap_state_setup (event, skb, frame)
+ *
+ *    SETUP state, The local layer has transmitted a SNRM command frame to
+ *    a remote peer layer and is awaiting a reply .
+ *
+ */
+static int irlap_state_setup( struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case FINAL_TIMER_EXPIRED:
+		if ( self->retry_count < self->N3) {
+/* 
+ *  Perform random backoff, Wait a random number of time units, minimum 
+ *  duration half the time taken to transmitt a SNRM frame, maximum duration 
+ *  1.5 times the time taken to transmit a SNRM frame. So this time should 
+ *  between 15 msecs and 45 msecs.
+ */
+			irlap_start_backoff_timer( self, 2 + (jiffies % 3));
+		} else {
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+
+			irlap_disconnect_indication( self, LAP_FOUND_NONE);
+		}
+		break;
+	case BACKOFF_TIMER_EXPIRED:
+		irlap_send_snrm_frame( self, &self->qos_rx);
+		irlap_start_final_timer( self, self->final_timeout);
+		self->retry_count++;
+		break;
+
+	case RECV_SNRM_CMD:
+		DEBUG( 0, "irlap_state_setup: SNRM battle!\n");
+
+		ASSERT( skb != NULL, return 0;);
+		ASSERT( info != NULL, return 0;);
+
+		/*
+		 *  The device with the largest device address wins the battle
+		 *  (both have sent a SNRM command!)
+		 */
+		if ( info->daddr > self->saddr) {
+			del_timer( &self->final_timer);
+			irlap_initiate_connection_state( self);
+
+			ASSERT( self->irdev != NULL, return -1;);
+			irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+			
+			irlap_send_ua_response_frame(self, &self->qos_rx);
+			irlap_apply_connection_parameters( self, &self->qos_tx);
+			irlap_connect_confirm( self, skb);
+			
+			/* 
+			 *  The WD-timer could be set to the duration of the
+			 *  P-timer for this case, but it is recommomended
+			 *  to use twice the value (note 3 IrLAP p. 60).  
+			 */
+			irlap_start_wd_timer( self, self->wd_timeout);
+			
+			irlap_next_state( self, LAP_NRM_S);
+		} else {
+			/* We just ignore the other device! */
+			irlap_next_state( self, LAP_SETUP);
+		}
+		break;
+	case RECV_UA_RSP:
+		/* Stop F-timer */
+		del_timer( &self->final_timer);
+
+		/* Initiate connection state */
+		irlap_initiate_connection_state( self);
+
+		/* Negotiate connection parameters */
+		IS_SKB( skb, return -1;);
+		ASSERT( skb->len > 10, return -1;);
+		skb_pull( skb, 10);
+
+		ASSERT( self->irdev != NULL, return -1;);
+		irda_qos_negotiate( &self->qos_rx, &self->qos_tx, skb);
+
+		irlap_apply_connection_parameters( self, &self->qos_tx); 
+		self->retry_count = 0;
+		irlap_send_rr_frame( self, CMD_FRAME);
+
+		irlap_start_final_timer( self, self->final_timeout/2);
+		irlap_next_state( self, LAP_NRM_P);
+
+		irlap_connect_confirm( self, skb);
+		break;
+
+	case RECV_DISC_FRAME:
+		del_timer( &self->final_timer);
+		irlap_next_state( self, LAP_NDM);
+
+		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		break;
+
+       /* DM handled in irlap_frame.c, irlap_input() */
+		
+	default:
+		DEBUG( 4, "irlap_state_setup: Unknown event");
+		ret = -1;
+		break;
+	}	
+	return ret;
+}
+
+/*
+ * Function irlap_state_offline (self, event, skb, info)
+ *
+ *    OFFLINE state, not used for now!
+ *
+ */
+static int irlap_state_offline( struct irlap_cb *self, IRLAP_EVENT event, 
+				struct sk_buff *skb, struct irlap_info *info) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Unknown event\n");
+
+	return -1;
+}
+
+/*
+ * 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.  
+ *
+ */
+static int irlap_state_xmit_p( struct irlap_cb *self, IRLAP_EVENT event, 
+			       struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+	
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+
+	DEBUG( 4, __FUNCTION__ "(), event=%s, vs=%d, vr=%d", 
+	       irlap_event[ event], self->vs, self->vr); 
+		
+	switch( event) {
+	case SEND_I_CMD:
+		ASSERT( skb != NULL, return -1;);
+		DEBUG( 4, "irlap_state_xmit: Window=%d\n", self->window);
+		
+		/*
+		 *  Only send frame if send-window > 0.
+		 */ 
+		if (( self->window > 0) && ( !self->remote_busy)) {
+
+			/*
+			 *  Test if we have transmitted more bytes over the 
+			 *  link than its possible to do with the current 
+			 *  speed and turn-around-time.
+			 */
+			if (( skb->len+self->bofs_count) > self->bytes_left) {
+				DEBUG( 4, __FUNCTION__ "(), Not allowed to "
+				       "transmit more bytes!\n");
+				skb_queue_head( &self->tx_list, skb);
+
+				/*
+				 *  We should switch state to LAP_NRM_P, but
+				 *  that is not possible since we must be sure
+				 *  that we poll the other side. Since we have
+				 *  used up our time, the poll timer should
+				 *  trigger anyway now,so we just wait for it
+				 *  DB
+				 */
+				return -EPROTO;
+			}
+			self->bytes_left -= ( skb->len + self->bofs_count);
+
+			/*
+			 *  Send data with poll bit cleared only if window > 1
+			 *  and there is more frames after this one to be sent
+			 */
+			if (( self->window > 1) && 
+			    skb_queue_len( &self->tx_list) > 0) 
+			{   
+				DEBUG( 4, __FUNCTION__ "(), window > 1\n");
+				irlap_send_data_primary( self, skb);
+				irlap_next_state( self, LAP_XMIT_P);
+			} else {
+				DEBUG( 4, __FUNCTION__ "(), window <= 1\n");
+				irlap_send_data_primary_poll( self, skb);
+				irlap_next_state( self, LAP_NRM_P);
+			}
+#ifdef CONFIG_IRDA_FAST_RR
+			/* Peer may want to reply immediately */
+			self->fast_RR = FALSE;
+#endif
+		} else {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unable to send! remote busy?\n");
+			skb_queue_head( &self->tx_list, skb);
+
+			/*
+			 *  The next ret is important, because it tells 
+			 *  irlap_next_state _not_ to deliver more frames
+			 */
+			ret = -EPROTO;
+		}
+		break;
+	case DISCONNECT_REQUEST:
+		del_timer( &self->poll_timer);
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+		irlap_send_disc_frame( self);
+		irlap_flush_all_queues( self);
+		irlap_start_final_timer( self, self->final_timeout);
+		self->retry_count = 0;
+		irlap_next_state( self, LAP_PCLOSE);
+		break;
+	case POLL_TIMER_EXPIRED:
+		irlap_send_rr_frame( self, CMD_FRAME);
+		irlap_start_final_timer( self, self->final_timeout);
+		irlap_next_state( self, LAP_NRM_P);
+		break;
+	default:
+		/* DEBUG( 0, "irlap_state_xmit: Unknown event"); */
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_pclose (event, skb, info)
+ *
+ *    PCLOSE state
+ */
+static int irlap_state_pclose( struct irlap_cb *self, IRLAP_EVENT event, 
+			       struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);	
+
+	switch( event) {
+	case RECV_UA_RSP:
+		del_timer( &self->final_timer);
+		
+		irlap_apply_default_connection_parameters( self);
+
+		/* Always switch state before calling upper layers */
+		irlap_next_state( self, LAP_NDM);
+
+		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+
+		break;
+	case FINAL_TIMER_EXPIRED:
+		if ( self->retry_count < self->N3) {
+			irlap_wait_min_turn_around( self, &self->qos_tx);
+			irlap_send_disc_frame( self);
+			irlap_start_final_timer( self, self->final_timeout);
+			self->retry_count++;
+			/* Keep state */
+		} else {
+			irlap_apply_default_connection_parameters( self);
+
+			/* 
+			 *  Always switch state before calling upper layers 
+			 */
+			irlap_next_state( self, LAP_NDM);
+
+			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		}
+		break;
+	default:
+		DEBUG( 0, "irlap_state_pclose: Unknown event %d\n", event);
+		ret = -1;
+		break;	
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_nrm_p (self, event, skb, info)
+ *
+ *   NRM_P (Normal Response Mode as Primary), The primary station has given
+ *   permissions to a secondary station to transmit IrLAP resonse frames
+ *   (by sending a frame with the P bit set). The primary station will not
+ *   transmit any frames and is expecting to receive frames only from the
+ *   secondary to which transmission permissions has been given.
+ */
+static int irlap_state_nrm_p( struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+	int ns_status;
+	int nr_status;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case RECV_RR_RSP:
+		DEBUG( 4, "irlap_state_nrm_p: RECV_RR_FRAME: "
+		       "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n",
+		       self->retry_count, info->nr, self->va, self->vs, 
+		       self->vr);
+
+		ASSERT( info != NULL, return -1;);
+
+		/*  
+		 *  If you get a RR, the remote isn't busy anymore, 
+		 *  no matter what the NR 
+		 */
+		self->remote_busy = FALSE;
+
+		/* 
+		 *  Nr as expected? 
+		 */
+		ret = irlap_validate_nr_received( self, info->nr);
+		if ( ret == NR_EXPECTED) {	
+			/* Stop final timer */
+			del_timer( &self->final_timer);
+			
+			/* Update Nr received */
+			irlap_update_nr_received( self, info->nr);
+			
+			/*
+			 *  Got expected NR, so reset the retry_count. This 
+			 *  is not done by the IrLAP standard , which is 
+			 *  strange! DB.
+			 */
+			self->retry_count = 0;			
+			irlap_wait_min_turn_around( self, &self->qos_tx);
+
+			/* Start poll timer */
+			irlap_start_poll_timer( self, self->poll_timeout);
+
+			irlap_next_state( self, LAP_XMIT_P);
+		} else if ( ret == NR_UNEXPECTED) {
+			ASSERT( info != NULL, return -1;);	
+			/* 
+			 *  Unexpected nr! 
+			 */
+			
+			/* Update Nr received */
+			irlap_update_nr_received( self, info->nr);
+
+			DEBUG( 4, "RECV_RR_FRAME: Retrans:%d, nr=%d, va=%d, "
+			       "vs=%d, vr=%d\n",
+			       self->retry_count, info->nr, self->va, 
+			       self->vs, self->vr);
+			
+			/* Resend rejected frames */
+			irlap_resend_rejected_frames( self, CMD_FRAME);
+			
+			/*
+			 *  Start only if not running, DB
+			 *  TODO: Should this one be here?
+			 */
+			/* if ( !self->final_timer.prev) */
+/* 				irda_start_timer( FINAL_TIMER, self->final_timeout);  */
+
+			/* 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");
+			del_timer( &self->final_timer);
+
+			irlap_next_state( self, LAP_RESET_WAIT);
+
+			irlap_disconnect_indication( self, 
+						     LAP_RESET_INDICATION);
+			self->xmitflag = TRUE;
+		}
+		if (skb)
+			dev_kfree_skb( skb);
+		break;
+	case RECV_RNR_FRAME:
+		DEBUG( 4, "irlap_state_nrm_p: RECV_RNR_FRAME: Retrans:%d, "
+		       "nr=%d, va=%d, vs=%d, vr=%d\n",
+		       self->retry_count, info->nr, self->va, self->vs, 
+		       self->vr);
+
+		ASSERT( info != NULL, return -1;);
+
+		/* Stop final timer */
+		del_timer( &self->final_timer);
+		self->remote_busy = TRUE;
+
+		/* Update Nr received */
+		irlap_update_nr_received( self, info->nr);
+			
+		/* Start poll timer */
+		irlap_start_poll_timer( self, self->poll_timeout);
+
+		irlap_next_state( self, LAP_XMIT_P);
+
+		dev_kfree_skb( skb);
+		break;
+	case RECV_I_RSP:
+		/* FIXME: must check for remote_busy below */
+#ifdef CONFIG_IRDA_FAST_RR
+		/* 
+		 *  Reset the fast_RR so we can use the fast RR code with
+		 *  full speed the next time since peer may have more frames
+		 *  to transmitt
+		 */
+		self->fast_RR = FALSE;
+#endif
+
+		ASSERT( info != NULL, return -1;);
+
+		ns_status = irlap_validate_ns_received( self, info->ns);
+		nr_status = irlap_validate_nr_received( self, info->nr);
+
+		/* 
+		 *  Check for expected I(nformation) frame
+		 */
+		if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) {
+			/* 
+			 *  poll bit cleared?
+			 */
+			if ( !info->pf) {
+				self->vr = (self->vr + 1) % 8;
+			
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				self->ack_required = TRUE;
+				
+				/* Keep state, do not move this line */
+				irlap_next_state( self, LAP_NRM_P);
+				
+				irlap_data_indication( self, skb);
+			} else {
+				del_timer( &self->final_timer);
+
+				self->vr = (self->vr + 1) % 8;
+			
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+		
+				/*  
+				 *  Got expected NR, so reset the
+				 *  retry_count. This is not done by IrLAP,
+				 *  which is strange!  
+				 */
+				self->retry_count = 0;
+				self->ack_required = TRUE;
+			
+				/* This is the last frame */
+				irlap_start_poll_timer( self, self->poll_timeout);
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+				/* Do not move this line */
+				irlap_next_state( self, LAP_XMIT_P);
+			
+				irlap_data_indication( self, skb);
+			}
+			break;
+			
+		}
+		/*
+		 *  Unexpected next to send (Ns)
+		 */
+		if (( ns_status == NS_UNEXPECTED) && 
+		    ( nr_status == NR_EXPECTED)) 
+		{
+			if ( !info->pf) {
+				irlap_update_nr_received( self, info->nr);
+				
+				/*
+				 *  Wait until the last frame before doing 
+				 *  anything
+				 */
+
+				/* Keep state */
+				irlap_next_state( self, LAP_NRM_P);
+			} else {
+				DEBUG( 4, "*** irlap_state_nrm_p:"
+				       " missing or duplicate frame!\n");
+				
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_send_rr_frame( self, CMD_FRAME);
+				
+				self->ack_required = FALSE;
+			
+				irlap_start_final_timer( self, self->final_timeout);
+				irlap_next_state( self, LAP_NRM_P);
+			}
+			dev_kfree_skb( skb);
+			break;
+		}
+		/* 
+		 *  Unexpected next to receive (Nr) 
+		 */
+		if (( ns_status == NS_EXPECTED) && 
+		    ( nr_status == NR_UNEXPECTED))
+		{
+			if ( info->pf) {
+				self->vr = (self->vr + 1) % 8;
+			
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+			
+				/* Resend rejected frames */
+				irlap_resend_rejected_frames( self, CMD_FRAME);
+				
+				self->ack_required = FALSE;
+				irlap_start_final_timer( self, self->final_timeout);
+				
+				/* Keep state, do not move this line */
+				irlap_next_state( self, LAP_NRM_P);
+				
+				irlap_data_indication( self, skb);
+			} else {
+				/* 
+				 *  Do not resend frames until the last
+				 *  frame has arrived from the other
+				 *  device. This is not documented in
+				 *  IrLAP!!  
+				 */
+				self->vr = (self->vr + 1) % 8;
+
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				self->ack_required = FALSE;
+
+				/* Keep state, do not move this line!*/
+				irlap_next_state( self, LAP_NRM_P); 
+				
+				irlap_data_indication( self, skb);
+			}
+			break;
+		}
+		/*
+		 *  Unexpected next to send (Ns) and next to receive (Nr)
+		 *  Not documented by IrLAP!
+		 */
+		if (( ns_status == NS_UNEXPECTED) && 
+		    ( nr_status == NR_UNEXPECTED)) 
+		{
+			DEBUG( 4, "IrLAP: unexpected nr and ns!\n");
+			if ( info->pf) {
+				/* Resend rejected frames */
+				irlap_resend_rejected_frames( self, CMD_FRAME);
+				
+				/* Give peer some time to retransmit! */
+				irlap_start_final_timer( self, self->final_timeout);
+
+				/* Keep state, do not move this line */
+				irlap_next_state( self, LAP_NRM_P);
+			} else {
+				/* Update Nr received */
+				/* irlap_update_nr_received( info->nr); */
+				
+				self->ack_required = FALSE;
+			}
+			break;
+		}
+
+		/*
+		 *  Invalid NR or NS
+		 */
+		if (( nr_status == NR_INVALID) || ( ns_status == NS_INVALID)) {
+			if ( info->pf) {
+				del_timer( &self->final_timer);
+				
+				irlap_next_state( self, LAP_RESET_WAIT);
+
+				irlap_disconnect_indication( self, LAP_RESET_INDICATION);
+				self->xmitflag = TRUE;
+			} else {
+				del_timer( &self->final_timer);
+				
+				irlap_disconnect_indication( self, LAP_RESET_INDICATION);
+				
+				self->xmitflag = FALSE;
+			}
+			break;
+		}
+		DEBUG( 0, "irlap_state_nrm_p: Not implemented!\n");
+		DEBUG( 0, "event=%s, ns_status=%d, nr_status=%d\n", 
+		       irlap_event[ event], ns_status, nr_status);
+		break;
+	case RECV_UI_FRAME:
+		/*  poll bit cleared?  */
+		if ( !info->pf) {
+			irlap_unit_data_indication( self, skb);
+			irlap_next_state( self, LAP_NRM_P);
+		} else {
+			del_timer( &self->final_timer);
+			irlap_unit_data_indication( self, skb);
+			irlap_start_poll_timer( self, self->poll_timeout);
+		}
+		break;
+	case RECV_FRMR_RSP:
+		del_timer( &self->final_timer);
+		self->xmitflag = TRUE;
+		irlap_next_state( self, LAP_RESET_WAIT);
+		irlap_reset_indication( self);
+		break;
+	case FINAL_TIMER_EXPIRED:
+		/* 
+		 *  We are allowed to wait for additional 300 ms if
+		 *  final timer expires when we are in the middle
+		 *  of receiving a frame (page 45, IrLAP). Check that
+		 *  we only do this once for each frame.
+		 */
+		if ( irda_device_is_receiving( self->irdev) && 
+		     !self->add_wait) {
+			DEBUG( 4, "FINAL_TIMER_EXPIRED when receiving a "
+			       "frame! Waiting a little bit more!\n");
+			irlap_start_final_timer( self, 30);
+
+			/*
+			 *  Don't allow this to happen one more time in a row, 
+			 *  or else we can get a pretty tight loop here if 
+			 *  if we only receive half a frame. DB.
+			 */
+			self->add_wait = TRUE;
+			break;
+		}
+		self->add_wait = FALSE;
+
+		if (( self->retry_count < self->N2) && 
+		    ( self->retry_count != self->N1)) {
+			
+			irlap_wait_min_turn_around( self, &self->qos_tx);
+			irlap_send_rr_frame( self, CMD_FRAME);
+			
+			irlap_start_final_timer( self, self->final_timeout);
+		 	self->retry_count++;
+
+			DEBUG( 4, "irlap_state_nrm_p: FINAL_TIMER_EXPIRED:"
+			       " retry_count=%d\n", self->retry_count);
+			/* Keep state */
+		} else if ( self->retry_count == self->N1) {
+			irlap_status_indication( STATUS_NO_ACTIVITY);
+			irlap_wait_min_turn_around( self, &self->qos_tx);
+			irlap_send_rr_frame( self, CMD_FRAME);
+			
+			irlap_start_final_timer( self, self->final_timeout);
+			self->retry_count++;
+
+			DEBUG( 4, "retry count = N1; retry_count=%d\n", 
+			       self->retry_count);
+			/* Keep state */
+		} else if ( self->retry_count >= self->N2) {
+			irlap_apply_default_connection_parameters( self);
+
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		}
+		break;
+	case RECV_DISC_FRAME: /* FIXME: Check how this is in the standard! */
+		DEBUG( 0, __FUNCTION__ "(), RECV_DISC_FRAME()\n");
+
+		/* Always switch state before calling upper layers */
+		irlap_next_state( self, LAP_NDM);
+		
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+		irlap_send_ua_response_frame( self, NULL);
+
+ 		del_timer( &self->final_timer);
+		/* del_timer( &self->poll_timer); */
+
+		irlap_flush_all_queues( self);
+		irlap_apply_default_connection_parameters( self);
+
+		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		if (skb)
+			dev_kfree_skb( skb);
+		
+		break;
+	default:
+		/* DEBUG( 0, "irlap_state_nrm_p: Unknown event"); */
+		ret = -1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_reset_wait (event, skb, info)
+ *
+ *    We have informed the service user of a reset condition, and is
+ *    awaiting reset of disconnect request.
+ *
+ */
+int irlap_state_reset_wait( struct irlap_cb *self, IRLAP_EVENT event, 
+			    struct sk_buff *skb, struct irlap_info *info)
+{
+	int ret = 0;
+	
+	DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	
+	switch( event) {
+	case RESET_REQUEST:
+		if ( self->xmitflag) {
+			irlap_wait_min_turn_around( self, &self->qos_tx);
+			irlap_send_snrm_frame( self, NULL);
+			irlap_start_final_timer( self, self->final_timeout);
+			irlap_next_state( self, LAP_RESET);
+		} else {
+			irlap_start_final_timer( self, self->final_timeout);
+			irlap_next_state( self, LAP_RESET);
+		}
+		break;
+	case DISCONNECT_REQUEST:
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+		irlap_send_disc_frame( self);
+		irlap_flush_all_queues( self);
+		irlap_start_final_timer( self, self->final_timeout);
+		self->retry_count = 0;
+		irlap_next_state( self, LAP_PCLOSE);
+		break;
+	default:
+		DEBUG( 0, "irlap_state_reset_wait: Unknown event %s\n", 
+		       irlap_event[event]);
+		ret = -1;
+		break;	
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_reset (self, event, skb, info)
+ *
+ *    We have sent a SNRM reset command to the peer layer, and is awaiting
+ *    reply.
+ *
+ */
+int irlap_state_reset( struct irlap_cb *self, IRLAP_EVENT event, 
+		       struct sk_buff *skb, struct irlap_info *info)
+{
+	int ret = 0;
+	
+	DEBUG( 3, __FUNCTION__ "(), event = %s\n", irlap_event[event]);
+	
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	
+	switch( event) {
+	case RECV_DISC_FRAME:
+		del_timer( &self->final_timer);
+
+		irlap_apply_default_connection_parameters( self);
+
+		/* Always switch state before calling upper layers */
+		irlap_next_state( self, LAP_NDM);
+
+		irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		break;
+	case RECV_UA_RSP:
+		del_timer( &self->final_timer);
+		
+		/* Initiate connection state */
+		irlap_initiate_connection_state( self);
+		
+		irlap_reset_confirm();
+		
+		self->remote_busy = FALSE;
+		irlap_start_poll_timer( self, self->poll_timeout);
+		irlap_next_state( self, LAP_XMIT_P);
+		break;
+	case FINAL_TIMER_EXPIRED:
+		if ( self->retry_count < 3) {
+			irlap_wait_min_turn_around( self, &self->qos_tx);
+
+			ASSERT( self->irdev != NULL, return -1;);
+			irlap_send_snrm_frame(self, 
+					      irda_device_get_qos( self->irdev));
+
+			self->retry_count++; /* Experimental!! */
+
+			irlap_start_final_timer( self, self->final_timeout);
+			irlap_next_state( self, LAP_RESET);
+		} else if ( self->retry_count >= self->N3) {
+			irlap_apply_default_connection_parameters( self);
+			
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+			
+			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		}
+		break;
+
+	case RECV_SNRM_CMD:
+		DEBUG(3, "lap_reset: RECV_SNRM_CMD\n");
+		irlap_initiate_connection_state( self);
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+		irlap_send_ua_response_frame( self, &self->qos_rx);
+		irlap_reset_confirm();
+		irlap_start_wd_timer( self, self->wd_timeout);
+		irlap_next_state( self, LAP_NDM);
+		break;
+
+	default:
+		DEBUG( 0, "irlap_state_reset: Unknown event %s\n", 
+		       irlap_event[ event]);
+		ret = -1;
+		break;	
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_xmit_s (event, skb, info)
+ * 
+ *   XMIT_S, The secondary station has been given the right to transmit,
+ *   and we therefor do not expect to receive any transmissions from other
+ *   stations.  
+ */
+static int irlap_state_xmit_s( struct irlap_cb *self, IRLAP_EVENT event, 
+			       struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+	
+	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	
+	switch( event) {
+	case SEND_I_CMD:
+		ASSERT( skb != NULL, return -1;);
+		DEBUG( 4, "irlap_state_xmit: Window=%d\n", self->window);
+		
+		/*
+		 *  Send frame only if send window > 1
+		 */ 
+		if (( self->window > 0) && ( !self->remote_busy)) {
+			/*
+			 *  Test if we have transmitted more bytes over the 
+			 *  link than its possible to do with the current 
+			 *  speed and turn-around-time.
+			 */
+			if (( skb->len+self->bofs_count) > self->bytes_left) {
+				DEBUG( 4, "IrDA: Not allowed to transmit more bytes!\n");
+				skb_queue_head( &self->tx_list, skb);
+				/*
+				 *  Switch to NRM_S, this is only possible
+				 *  when we are in secondary mode, since we 
+				 *  must be sure that we don't miss any RR
+				 *  frames
+				 */
+				irlap_next_state( self, LAP_NRM_S);
+
+				return -EPROTO; /* Try again later */
+			}
+			self->bytes_left -= ( skb->len + self->bofs_count);
+
+			/*
+			 *  Send data with final bit cleared only if window > 1
+			 *  and there is more frames to be sent
+			 */
+			if (( self->window > 1) && 
+			    skb_queue_len( &self->tx_list) > 0) 
+			{   
+				DEBUG( 4, "irlap_state_xmit: window > 1\n");
+				irlap_send_data_secondary( self, skb);
+				irlap_next_state( self, LAP_XMIT_S);
+			} else {
+				DEBUG( 4, "irlap_state_xmit: window <= 1\n");
+				irlap_send_data_secondary_final( self, skb);
+				irlap_next_state( self, LAP_NRM_S);
+			}
+		} else {
+			DEBUG( 0, "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]);
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_nrm_s (event, skb, info)
+ *
+ *    NRM_S (Normal Response Mode as Secondary) state, in this state we are 
+ *    expecting to receive frames from the primary station
+ *
+ */
+static int irlap_state_nrm_s( struct irlap_cb *self, IRLAP_EVENT event, 
+			      struct sk_buff *skb, struct irlap_info *info) 
+{
+	int ret = 0;
+	int ns_status;
+	int nr_status;
+
+	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+
+	switch( event) {
+	case RECV_RR_CMD:
+		self->retry_count = 0;
+
+		/* 
+		 *  Nr as expected? 
+		 */
+		nr_status = irlap_validate_nr_received( self, info->nr);
+		if ( nr_status == NR_EXPECTED) {
+			if (( skb_queue_len( &self->tx_list) > 0) && 
+			    ( self->window > 0)) {
+				self->remote_busy = FALSE;
+				
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				del_timer( &self->wd_timer);
+				
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_next_state( self, LAP_XMIT_S);
+			} else {			
+				self->remote_busy = FALSE;
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+				
+				irlap_send_rr_frame( self, RSP_FRAME);
+				
+				irlap_start_wd_timer( self, self->wd_timeout);
+				irlap_next_state( self, LAP_NRM_S);
+			}
+		} else if ( nr_status == NR_UNEXPECTED) {
+			self->remote_busy = FALSE;
+			irlap_update_nr_received( self, info->nr);
+			irlap_resend_rejected_frames( self, RSP_FRAME);
+
+			irlap_start_wd_timer( self, self->wd_timeout);
+
+			/* Keep state */
+			irlap_next_state( self, LAP_NRM_S); 
+		} else {
+			DEBUG( 0, "irlap_state_nrm_s: **** "
+			       "invalid nr not implemented!\n");
+		} 
+		if ( skb)
+			dev_kfree_skb( skb);
+
+		break;
+	case RECV_I_CMD:
+		/* FIXME: must check for remote_busy below */
+		DEBUG( 4, __FUNCTION__ "(), event=%s nr=%d, vs=%d, ns=%d, "
+		       "vr=%d, pf=%d\n", irlap_event[event], info->nr, 
+		       self->vs, info->ns, self->vr, info->pf);
+
+		self->retry_count = 0;
+
+		ns_status = irlap_validate_ns_received( self, info->ns);
+		nr_status = irlap_validate_nr_received( self, info->nr);
+		/* 
+		 *  Check for expected I(nformation) frame
+		 */
+		if ((ns_status == NS_EXPECTED) && (nr_status == NR_EXPECTED)) {
+			/* 
+			 *  poll bit cleared?
+			 */
+			if ( !info->pf) {
+				self->vr = (self->vr + 1) % 8;
+				
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				self->ack_required = TRUE;
+				
+				/*
+				 *  Starting WD-timer here is optional, but
+				 *  not recommended. Note 6 IrLAP p. 83
+				 */
+				/* irda_start_timer( WD_TIMER, self->wd_timeout); */
+
+				/* Keep state, do not move this line */
+				irlap_next_state( self, LAP_NRM_S);
+				
+				irlap_data_indication( self, skb);
+				break;
+			} else {
+				self->vr = (self->vr + 1) % 8;
+				
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				/* 
+				 *  We should wait before sending RR, and
+				 *  also before changing to XMIT_S
+				 *  state. (note 1, IrLAP p. 82) 
+				 */
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+				/*
+				 *  Any pending data requests?
+				 */
+				if (( skb_queue_len( &self->tx_list) > 0) && 
+				    ( self->window > 0)) 
+				{
+					self->ack_required = TRUE;
+					
+					del_timer( &self->wd_timer);
+					
+					irlap_next_state( self, LAP_XMIT_S);
+				} else {
+					irlap_send_rr_frame( self, RSP_FRAME);
+					irlap_start_wd_timer( self, self->wd_timeout);
+
+					/* Keep the state */
+					irlap_next_state( self, LAP_NRM_S);
+				}
+				irlap_data_indication( self, skb);
+
+				break;
+			}
+		}
+		/*
+		 *  Check for Unexpected next to send (Ns)
+		 */
+		if (( ns_status == NS_UNEXPECTED) && 
+		    ( nr_status == NR_EXPECTED)) 
+		{
+			/* Unexpected next to send, with final bit cleared */
+			if ( !info->pf) {
+				irlap_update_nr_received( self, info->nr);
+				
+				irlap_start_wd_timer( self, self->wd_timeout);
+			} else {
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+			
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+				irlap_send_rr_frame( self, CMD_FRAME);
+			
+				irlap_start_wd_timer( self, self->wd_timeout);
+			}
+			dev_kfree_skb( skb);
+			break;
+		}
+
+		/* 
+		 *  Unexpected Next to Receive(NR) ?
+		 */
+		if (( ns_status == NS_EXPECTED) && 
+		    ( nr_status == NR_UNEXPECTED))
+		{
+			if ( info->pf) {
+				DEBUG( 4, "RECV_I_RSP: frame(s) lost\n");
+				
+				self->vr = (self->vr + 1) % 8;
+				
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				/* Resend rejected frames */
+				irlap_resend_rejected_frames( self, RSP_FRAME);
+
+				/* Keep state, do not move this line */
+				irlap_next_state( self, LAP_NRM_S);
+
+				irlap_data_indication( self, skb);
+				irlap_start_wd_timer( self, self->wd_timeout);
+
+				break;
+			}
+			/*
+			 *  This is not documented in IrLAP!! Unexpected NR
+			 *  with poll bit cleared
+			 */
+			if ( !info->pf) {
+				self->vr = (self->vr + 1) % 8;
+				
+				/* Update Nr received */
+				irlap_update_nr_received( self, info->nr);
+				
+				/* Keep state, do not move this line */
+				irlap_next_state( self, LAP_NRM_S);
+				
+				irlap_data_indication( self, skb);
+				irlap_start_wd_timer( self, self->wd_timeout);
+			}
+		}
+		
+		if ( ret == NR_INVALID) {
+			DEBUG( 0, "NRM_S, NR_INVALID not implemented!\n");
+		}
+		if ( ret == NS_INVALID) {
+			DEBUG( 0, "NRM_S, NS_INVALID not implemented!\n");
+		}
+		break;
+	case RECV_UI_FRAME:
+		/* 
+		 *  poll bit cleared?
+		 */
+		if ( !info->pf) {
+			irlap_unit_data_indication( self, skb);
+			irlap_next_state( self, LAP_NRM_S); /* Keep state */
+		} else {
+			/*
+			 *  Any pending data requests?
+			 */
+			if (( skb_queue_len( &self->tx_list) > 0) && 
+			    ( self->window > 0) && !self->remote_busy) 
+			{
+				irlap_unit_data_indication( self, skb);
+				
+				del_timer( &self->wd_timer);
+
+				irlap_next_state( self, LAP_XMIT_S);
+			} else {
+				irlap_unit_data_indication( self, skb);
+
+				irlap_wait_min_turn_around( self, &self->qos_tx);
+
+				irlap_send_rr_frame( self, RSP_FRAME);
+				self->ack_required = FALSE;
+				
+				irlap_start_wd_timer( self, self->wd_timeout);
+
+				/* Keep the state */
+				irlap_next_state( self, LAP_NRM_S);
+			}
+		}
+		break;
+	case RECV_SNRM_CMD:
+#if 1
+		del_timer( &self->wd_timer);
+		DEBUG( 0, "irlap_state_nrm_s: received SNRM cmd\n");
+		irlap_next_state( self, LAP_RESET);
+#else
+		irlap_wait_min_turn_around( &self->qos_session);
+		irlap_send_ua_response_frame( &self->qos_session);
+		irda_start_timer( WD_TIMER, self->wd_timeout);
+		irlap_next_state( self, LAP_SCLOSE)
+		
+#endif
+		break;
+	case WD_TIMER_EXPIRED:
+		DEBUG( 4, "WD_TIMER_EXPIRED: %ld\n", jiffies);
+	
+		/*
+		 *  Wait until  retry_count * n matches negotiated threshold/
+		 *  disconnect time (note 2 in IrLAP p. 82)
+		 */
+		DEBUG( 0, "retry_count = %d\n", self->retry_count);
+
+		if (( self->retry_count < (self->N2/2))  && 
+		    ( self->retry_count != self->N1/2)) {
+			
+			irlap_start_wd_timer( self, self->wd_timeout);
+			self->retry_count++;		
+		} else if ( self->retry_count == (self->N1/2)) {
+			irlap_status_indication( STATUS_NO_ACTIVITY);
+			irlap_start_wd_timer( self, self->wd_timeout);
+			self->retry_count++;
+		} else if ( self->retry_count >= self->N2/2) {
+			irlap_apply_default_connection_parameters( self);
+			
+			/* Always switch state before calling upper layers */
+			irlap_next_state( self, LAP_NDM);
+			
+			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
+		}
+		break;
+
+	case RECV_DISC_FRAME:
+		/* Always switch state before calling upper layers */
+		irlap_next_state( self, LAP_NDM);
+
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+		irlap_send_ua_response_frame( self, NULL);
+		del_timer( &self->wd_timer);
+		irlap_flush_all_queues( self);
+		irlap_apply_default_connection_parameters( self);
+
+		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		if (skb)
+			dev_kfree_skb( skb);
+		
+		break;
+
+	case RECV_DISCOVERY_XID_CMD:
+		DEBUG( 3, "irlap_state_nrm_s: got event RECV_DISCOVER_XID_CMD!\n");
+		del_timer( &self->final_timer);
+		
+		irlap_apply_default_connection_parameters( self);
+
+		/* Always switch state before calling upper layers */
+		irlap_next_state( self, LAP_NDM);
+
+		irlap_disconnect_indication( self, LAP_DISC_INDICATION);
+		
+#if 0
+		irlap_wait_min_turn_around( self, &self->qos_session);
+		irlap_send_rr_frame( RSP_FRAME);
+		irda_start_timer( WD_TIMER, self->wd_timeout);
+		irlap_next_state( self, LAP_NRM_S);
+#endif
+		break;
+
+	default:
+		DEBUG( 0, "irlap_state_nrm_s: Unknown event %d, (%s)\n", 
+		       event, irlap_event[event]);
+		ret = -1;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * Function irlap_state_sclose (self, event, skb, info)
+ *
+ *    
+ *
+ */
+static int irlap_state_sclose( struct irlap_cb *self, IRLAP_EVENT event, 
+			       struct sk_buff *skb, struct irlap_info *info) 
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+
+	return -1;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.1.131/linux/net/irda/irlap_frame.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlap_frame.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1420 @@
+/*********************************************************************
+ *                
+ * Filename:      irlap_frame.c
+ * Version:       0.3
+ * 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:   Mon Dec 14 14:24:05 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Resrved.
+ *     
+ *     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/config.h>
+#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>
+#include <net/pkt_sched.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irda_device.h>
+#include <net/irda/irlap.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/timer.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/qos.h>
+
+extern __u8 *irlmp_hint_to_service( __u8 *hint);
+
+/*
+ * Function irlap_insert_mtt (self, skb)
+ *
+ *    Insert minimum turnaround time relevant information into the skb. We 
+ *    need to do this since it's per packet relevant information.
+ *
+ */
+__inline__ void irlap_insert_mtt( struct irlap_cb *self, struct sk_buff *skb)
+{
+	struct irlap_skb_cb *cb;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	cb = (struct irlap_skb_cb *) skb->cb;
+	
+	cb->mtt = self->mtt_required;
+	
+	/* Reset */
+	self->mtt_required = 0;
+	
+	/* 
+	 * Delay equals negotiated BOFs count plus the number of BOFs to 
+	 * force the negotiated minimum turnaround time 
+	 */
+	cb->xbofs = self->bofs_count+self->xbofs_delay;
+	
+	/* Reset XBOF's delay (used only for getting min turn time) */
+	self->xbofs_delay = 0;
+
+	DEBUG( 4, __FUNCTION__ "(), using %d xbofs\n", cb->xbofs);
+}
+
+/*
+ * Function irlap_send_connect_snrm_cmd (void)
+ *
+ *    Transmits a connect SNRM command frame
+ */
+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");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	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);
+		return;
+	}
+
+	skb_put( skb, 2); 
+	frame = skb->data;
+
+	/* Insert address field */
+	frame[n] = CMD_FRAME;
+	frame[n++] |= (qos) ? CBROADCAST : self->caddr;
+
+	/* Insert control field */
+ 	frame[n++] = SNRM_CMD | PF_BIT;
+	
+	/*
+	 *  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;
+
+		frame[n++] = self->caddr;
+				
+		/* skb_put( skb, 21); */
+		len = irda_insert_qos_negotiation_params( qos, frame+n);
+		/* Should not be dangerous to do this afterwards */
+		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++;
+}
+
+/*
+ * Function irlap_recv_snrm_cmd (skb, info)
+ *
+ *    Received SNRM (Set Normal Response Mode) command frame
+ *
+ */
+static void irlap_recv_snrm_cmd( struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info) 
+{
+	struct snrm_frame *frame;
+
+	DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
+
+	ASSERT( skb != NULL, return;);
+	ASSERT( info != NULL, return;);
+
+	frame = ( struct snrm_frame *) skb->data;
+
+	/* Copy peer device address */
+	memcpy( &info->daddr, &frame->saddr, 4);
+
+	/* Copy connection address */
+	info->caddr = frame->ncaddr;
+
+	irlap_do_event( self, RECV_SNRM_CMD, skb, info);
+}
+
+/*
+ * Function irlap_send_ua_response_frame (qos)
+ *
+ *    Send UA (Unnumbered Acknowledgement) frame
+ *
+ */
+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);
+	
+	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);
+		return;
+	}
+
+	skb_put( skb, 10);
+	frame = skb->data;
+	
+	/* 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;
+	
+	/* Should we send QoS negotiation parameters? */
+	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++;
+}
+
+
+/*
+ * Function irlap_send_dm_frame (void)
+ *
+ *    Send disconnected mode (DM) frame
+ *
+ */
+void irlap_send_dm_frame( struct irlap_cb *self)
+{
+	struct sk_buff *skb = NULL;
+	__u8 *frame;
+	
+	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);
+		return;
+	}
+
+	skb_put( skb, 2);
+	frame = skb->data;
+	
+	if ( self->state == LAP_NDM)
+		frame[0] = CBROADCAST;
+	else
+		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++;
+}
+
+/*
+ * Function irlap_send_disc_frame (void)
+ *
+ *    Send disconnect (DISC) frame
+ *
+ */
+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;);
+
+	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);
+		return;
+	}
+
+	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++;
+}
+
+/*
+ * Function irlap_send_discovery_xid_frame (S, s, command)
+ *
+ *    Build and transmit a XID (eXchange station IDentifier) discovery
+ *    frame. 
+ */
+void irlap_send_discovery_xid_frame( struct irlap_cb *self, int S, __u8 s, 
+				     __u8 command, DISCOVERY *discovery) 
+{
+	struct sk_buff *skb = NULL;
+	struct xid_frame *frame;
+	__u32 bcast = BROADCAST;
+
+ 	DEBUG( 4, __FUNCTION__ "(), s=%d, S=%d, command=%d\n", s, S, command);
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( discovery != NULL, return;);
+
+	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);
+		return;
+	}
+
+	skb_put( skb, 14);
+	frame = ( struct xid_frame *) skb->data;
+
+	if ( command) {
+		frame->caddr = CBROADCAST | CMD_FRAME;
+		frame->control =  XID_CMD | PF_BIT;
+	} else {
+		frame->caddr = CBROADCAST;
+		frame->control =  XID_RSP | PF_BIT;
+	}
+	frame->ident = XID_FORMAT;
+
+	memcpy( &frame->saddr, &self->saddr, 4);
+
+	if ( command)
+		memcpy( &frame->daddr, &bcast, 4);
+	else
+		memcpy( &frame->daddr, &self->daddr, 4);	
+	
+	switch( S) {
+	case 1:
+		frame->flags = 0x00;
+		break;
+	case 6:
+		frame->flags = 0x01;
+		break;
+	case 8:
+		frame->flags = 0x02;
+		break;
+	case 16:
+		frame->flags = 0x03;
+		break;
+	default:
+		frame->flags = 0x02;
+		break;
+	}
+
+	frame->slotnr = s; 
+	frame->version = 0x00;
+
+	/*  
+	 *  Provide info for final slot only in commands, and for all
+	 *  responses. Send the second byte of the hint only if the
+	 *  EXTENSION bit is set in the first byte.
+	 */
+	if ( !command || ( frame->slotnr == 0xff)) {
+		int i;
+
+		if( discovery->hint[0] & HINT_EXTENSION)
+			skb_put( skb, 3+discovery->info_len);
+		else
+			skb_put( skb, 2+discovery->info_len);
+		
+		i = 0;
+		frame->discovery_info[i++] = discovery->hint[0];
+		if( discovery->hint[0] & HINT_EXTENSION)
+			frame->discovery_info[i++] = discovery->hint[1];
+		
+		frame->discovery_info[i++] = discovery->charset;
+
+		ASSERT( discovery->info_len < 30, return;);
+
+		memcpy( &frame->discovery_info[i++], discovery->info, 
+			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++;
+}
+
+/*
+ * Function irlap_recv_discovery_xid_rsp (skb, info)
+ *
+ *    Received a XID discovery response
+ *
+ */
+static void irlap_recv_discovery_xid_rsp( struct irlap_cb *self, 
+					  struct sk_buff *skb, 
+					  struct irlap_info *info) 
+{
+	struct xid_frame *xid;
+	DISCOVERY *discovery = NULL;
+	char *text;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( info != NULL, return;);
+
+	if (( discovery = kmalloc( sizeof( DISCOVERY), GFP_ATOMIC)) == NULL) {
+		DEBUG( 0, __FUNCTION__ "(), kmalloc failed!\n");
+		return;
+	}
+	memset( discovery, 0, sizeof( DISCOVERY));
+
+	xid = (struct xid_frame *) skb->data;
+
+	/* 
+	 *  Copy peer device address and set the source address
+	 */
+	memcpy( &info->daddr, &xid->saddr, 4);
+	discovery->daddr = info->daddr;
+	discovery->saddr = self->saddr;
+
+	DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", discovery->daddr);
+
+	/* Get info returned from peer */
+	discovery->hint[0] = xid->discovery_info[0];
+	if ( xid->discovery_info[0] & HINT_EXTENSION) {
+		DEBUG( 4, "EXTENSION\n");
+		discovery->hint[1] = xid->discovery_info[1];
+		discovery->charset = xid->discovery_info[2];
+		text = (char *) &xid->discovery_info[3];
+	} else {
+		discovery->hint[1] = 0;
+		discovery->charset = xid->discovery_info[1];
+		text = (char *) &xid->discovery_info[2];
+	}
+	/* 
+	 *  Terminate string, should be safe since this is where the 
+	 *  FCS bytes resides.
+	 */
+	skb->data[skb->len] = '\0'; 
+	strcpy( discovery->info, text);
+
+	info->discovery = discovery;
+
+	irlap_do_event( self, RECV_DISCOVERY_XID_RSP, skb, info);
+}
+
+/*
+ * Function irlap_recv_discovery_xid_cmd (skb, info)
+ *
+ *    Received a XID discovery command
+ *
+ */
+static void irlap_recv_discovery_xid_cmd( struct irlap_cb *self, 
+					  struct sk_buff *skb, 
+					  struct irlap_info *info) 
+{
+	struct xid_frame *xid;
+	DISCOVERY *discovery = NULL;
+	char *text;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( info != NULL, return;);
+
+	xid = (struct xid_frame *) skb->data;
+	
+	/* Copy peer device address */
+	memcpy( &info->daddr, &xid->saddr, 4);
+
+	switch ( xid->flags & 0x03) {
+	case 0x00:
+		info->S = 1;
+		break;
+	case 0x01:
+		info->S = 6;
+		break;
+	case 0x02:
+		info->S = 8;
+		break;
+	case 0x03:
+		info->S = 16;
+		break;
+	default:
+		/* Error!! */
+		return;
+	}
+	info->s = xid->slotnr;
+	
+	/* 
+	 *  Check if last frame 
+	 */
+	if ( info->s == 0xff) {
+		/*
+		 *  We now have some discovery info to deliver!
+		 */
+		discovery = kmalloc( sizeof( DISCOVERY), GFP_ATOMIC);
+		if ( !discovery) {
+			DEBUG( 0, __FUNCTION__ "(), kmalloc failed!\n");
+			return;
+		}
+		discovery->daddr = info->daddr;
+		discovery->saddr = self->saddr;
+
+		DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", 
+		       discovery->daddr);
+
+		discovery->hint[0] = xid->discovery_info[0];
+		if ( xid->discovery_info[0] & HINT_EXTENSION) {
+			DEBUG( 4, "EXTENSION\n");
+			discovery->hint[1] = xid->discovery_info[1];
+			discovery->charset = xid->discovery_info[2];
+			text = (char *) &xid->discovery_info[3];
+		} else {
+			discovery->hint[1] = 0;
+			discovery->charset = xid->discovery_info[1];
+			text = (char *) &xid->discovery_info[2];
+		}
+		/* 
+		 *  Terminate string, should be safe since this is where the 
+		 *  FCS bytes resides.
+		 */
+		skb->data[skb->len] = '\0'; 
+		strcpy( discovery->info, text);
+
+		info->discovery = discovery;
+	} else
+		info->discovery = NULL;
+	
+	DEBUG( 4, __FUNCTION__"(), s=%d, S=%d <%ld>\n", 
+	       info->s, info->S, jiffies); 
+
+	irlap_do_event( self, RECV_DISCOVERY_XID_CMD, skb, info);
+}
+
+/*
+ * Function irlap_send_rr_frame (self, command)
+ *
+ *    Build and transmit RR (Receive Ready) frame. Notice that it is currently
+ *    only possible to send RR frames with the poll bit set.
+ */
+void irlap_send_rr_frame( struct irlap_cb *self, int command) 
+{
+	struct sk_buff *skb = NULL;
+	__u8 *frame;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+#ifdef CONFIG_IRDA_RECYCLE_RR
+	if ( self->recycle_rr_skb) {
+		DEBUG( 4, __FUNCTION__ "(), recycling skb!\n");
+		skb = self->recycle_rr_skb;
+		skb->stamp.tv_sec = 0;
+		self->recycle_rr_skb = NULL;
+	}
+#endif      
+	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);
+			return;
+		}
+		skb_put( skb, 2);
+	}
+	ASSERT( skb->len == 2, return;);
+
+	frame = skb->data;
+	
+	frame[0] = self->caddr;
+	frame[0] |= (command) ? CMD_FRAME : 0;
+
+	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);
+
+	dev_queue_xmit( skb);
+	self->stats.tx_packets++;
+}
+
+/*
+ * Function irlap_recv_rr_frame (skb, info)
+ *
+ *    Received RR (Receive Ready) frame from peer station
+ *
+ */
+static void irlap_recv_rr_frame( struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info, int command)
+{
+	__u8 *frame;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	frame = skb->data;
+	info->nr = frame[1] >> 5;
+
+	DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+
+	/*
+	 *  Make sure the state-machine is in the right state for receiving, 
+	 *  if not, then we just discard the received frame for now!
+	 *  TODO: check if we should queue this frame, or make tty tell that
+	 *  it is receiving frames until the frame is delivered instead of
+	 *  until it is outside a frame.
+	 */
+#if 0
+	if (( self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) {
+		DEBUG( 0, __FUNCTION__ "(), Wrong state, dropping frame!\n");
+		dev_kfree_skb( skb);
+		return;
+	}
+#endif
+
+#ifdef CONFIG_IRDA_RECYCLE_RR
+	/* Only recycle one RR frame */
+	if ( self->recycle_rr_skb == NULL) {
+
+		/* Keep this skb, so it can be reused */
+		self->recycle_rr_skb = skb;
+
+		/*  
+		 *  Set skb to NULL, so that the state machine will not 
+		 *  deallocate it.
+		 */
+		skb = NULL;  
+	}
+#endif
+	/* Check if this is a command or a response frame */
+	if ( command)
+		irlap_do_event( self, RECV_RR_CMD, skb, info);
+	else
+		irlap_do_event( self, RECV_RR_RSP, skb, info);
+}
+
+/*
+ * Function irlap_send_rr_frame ()
+ *
+ *    Build and transmit RR (Receive Ready) frame
+ */
+void irlap_send_frmr_frame( struct irlap_cb *self, int command)
+{
+	struct sk_buff *skb = NULL;
+	__u8 *frame;
+	
+	ASSERT( self != NULL, return;);
+	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);
+		return;
+	}
+
+	skb_put( skb, 2);
+	frame = skb->data;
+	
+	frame[0] = self->caddr;
+	frame[0] |= (command) ? CMD_FRAME : 0;
+
+	frame[1]  = (self->vs << 1);
+	frame[1] |= PF_BIT;
+	frame[1] |= (self->vr << 5);
+
+	frame[2] = 0;
+
+   	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++;
+}
+
+/*
+ * Function irlap_recv_rnr_frame (self, skb, info)
+ *
+ *    Received RNR (Receive Not Ready) frame from peer station
+ *
+ */
+static void irlap_recv_rnr_frame( struct irlap_cb *self, struct sk_buff *skb, 
+				  struct irlap_info *info) 
+{
+	__u8 *frame;
+
+	ASSERT( skb != NULL, return;);
+	ASSERT( info != NULL, return;);
+
+	frame = skb->data;
+	info->nr = frame[1] >> 5;
+
+	DEBUG( 4, __FUNCTION__ "(), nr=%d, %ld\n", info->nr, jiffies);
+
+	irlap_do_event( self, RECV_RNR_FRAME, skb, info);
+}
+
+/*
+ * Function irlap_recv_ua_frame (skb, frame)
+ *
+ *    Received UA (Unnumbered Acknowledgement) frame
+ *
+ */
+static void irlap_recv_ua_frame( struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info) 
+{
+ 	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( skb != NULL, return;);
+	ASSERT( info != NULL, return;);
+
+	irlap_do_event( self, RECV_UA_RSP, skb, info);
+}
+
+/*
+ * Function irlap_send_data_primary(self, skb)
+ *
+ *    
+ *
+ */
+void irlap_send_data_primary( struct irlap_cb *self, struct sk_buff *skb)
+{
+	struct sk_buff *tx_skb;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	/* Initialize variables */
+	tx_skb = NULL;
+
+	if ( skb->data[1] == I_FRAME) {
+
+		/*  
+		 *  Insert frame sequence number (Vs) in control field before
+		 *  inserting into transmit window queue.
+		 */
+		skb->data[1] = I_FRAME | (self->vs << 1);
+		
+		/* * 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;
+		}
+		
+		/*
+		 *  make sure the skb->sk accounting of memory usage is sane
+		 */
+		if (skb->sk != NULL)
+			skb_set_owner_w( tx_skb, skb->sk);
+		
+		/* 
+		 *  Insert frame in store, in case of retransmissions 
+		 */
+		skb_queue_tail( &self->wx_list, skb);
+		
+		self->vs = (self->vs + 1) % 8;
+		self->ack_required = FALSE;		
+		self->window -= 1;
+
+		irlap_send_i_frame( self, tx_skb, CMD_FRAME);
+	} else {
+		DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n");
+		irlap_send_ui_frame( self, skb, CMD_FRAME);
+		self->window -= 1;
+	}
+}
+/*
+ * Function irlap_send_data_primary_poll ( self, skb)
+ *
+ *    Send I(nformation) frame as primary with poll bit set
+ */
+void irlap_send_data_primary_poll( struct irlap_cb *self, struct sk_buff *skb) 
+{
+	struct sk_buff *tx_skb;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	IS_SKB( skb, return;);
+
+	/* Initialize variables */
+	tx_skb = NULL;
+
+	/* Is this reliable or unreliable data? */
+	if ( skb->data[1] == I_FRAME) {
+		
+		/*  
+		 *  Insert frame sequence number (Vs) in control field before
+		 *  inserting into transmit window queue.
+		 */
+		skb->data[1] = I_FRAME | (self->vs << 1);
+		
+		/* 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;
+		}
+		
+		/*
+		 *  make sure the skb->sk accounting of memory usage is sane
+		 */
+		if (skb->sk != NULL)
+			skb_set_owner_w( tx_skb, skb->sk);
+		
+		/* 
+		 *  Insert frame in store, in case of retransmissions 
+		 */
+		skb_queue_tail( &self->wx_list, skb);
+		
+		/*  
+		 *  Set poll bit if necessary. We do this to the copied
+		 *  skb, since retransmitted need to set or clear the poll
+		 *  bit depending on when * they are sent.  
+		 */
+		/* Stop P timer */
+		del_timer( &self->poll_timer);
+		
+		tx_skb->data[1] |= PF_BIT;
+		
+		self->vs = (self->vs + 1) % 8;
+		self->ack_required = FALSE;
+		self->window = self->window_size;
+
+		irlap_start_final_timer( self, self->final_timeout);
+
+		irlap_send_i_frame( self, tx_skb, CMD_FRAME);
+	} else {
+		DEBUG( 4, __FUNCTION__ "(), sending unreliable frame\n");
+
+		del_timer( &self->poll_timer);
+
+		if ( self->ack_required) {
+			irlap_send_ui_frame( self, skb, CMD_FRAME);
+			irlap_send_rr_frame( self, CMD_FRAME);
+			self->ack_required = FALSE;
+		} else {
+			skb->data[1] |= PF_BIT;
+			irlap_send_ui_frame( self, skb, CMD_FRAME);
+		}
+		self->window = self->window_size;
+		irlap_start_final_timer( self, self->final_timeout);
+	}
+}
+
+/*
+ * Function irlap_send_data_secondary_final (self, skb)
+ *
+ *    Send I(nformation) frame as secondary with final bit set
+ *
+ */
+void irlap_send_data_secondary_final( struct irlap_cb *self, 
+				      struct sk_buff *skb) 
+{
+	struct sk_buff *tx_skb = NULL;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	IS_SKB( skb,return;);
+
+	/* Is this reliable or unreliable data? */
+	if ( skb->data[1] == I_FRAME) {
+
+		/*  
+		 *  Insert frame sequence number (Vs) in control field before
+		 *  inserting into transmit window queue.
+		 */
+		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;
+		}		
+
+		if (skb->sk != NULL)
+			skb_set_owner_w( tx_skb, skb->sk);
+		
+		/* Insert frame in store */
+		skb_queue_tail( &self->wx_list, skb);
+		
+		tx_skb->data[1] |= PF_BIT;
+		
+		self->vs = (self->vs + 1) % 8; 
+		self->window = self->window_size;
+		self->ack_required = FALSE;
+		
+		irlap_start_wd_timer( self, self->wd_timeout);
+
+		irlap_send_i_frame( self, tx_skb, RSP_FRAME); 
+	} else {
+		if ( self->ack_required) {
+			irlap_send_ui_frame( self, skb, RSP_FRAME);
+			irlap_send_rr_frame( self, RSP_FRAME);
+			self->ack_required = FALSE;
+		} else {
+			skb->data[1] |= PF_BIT;
+			irlap_send_ui_frame( self, skb, RSP_FRAME);
+		}
+		self->window = self->window_size;
+
+		irlap_start_wd_timer( self, self->wd_timeout);
+	}
+}
+
+/*
+ * Function irlap_send_data_secondary (self, skb)
+ *
+ *    Send I(nformation) frame as secondary without final bit set
+ *
+ */
+void irlap_send_data_secondary( struct irlap_cb *self, struct sk_buff *skb) 
+{
+	struct sk_buff *tx_skb = NULL;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	IS_SKB( skb, return;);
+
+	/* Is this reliable or unreliable data? */
+	if ( skb->data[1] == I_FRAME) {
+		
+		/*  
+		 *  Insert frame sequence number (Vs) in control field before
+		 *  inserting into transmit window queue.
+		 */
+		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;
+		}		
+		
+		if (skb->sk != NULL)
+			skb_set_owner_w( tx_skb, skb->sk);
+		
+		/* Insert frame in store */
+		skb_queue_tail( &self->wx_list, skb);
+		
+		self->vs = (self->vs + 1) % 8;
+		self->ack_required = FALSE;		
+		self->window -= 1;
+
+		irlap_send_i_frame( self, tx_skb, RSP_FRAME); 
+	} else {
+		irlap_send_ui_frame( self, skb, RSP_FRAME);
+		self->window -= 1;
+	}
+}
+
+/*
+ * Function irlap_resend_rejected_frames (nr)
+ *
+ *    Resend frames which has not been acknowledged. TODO: check that the 
+ *    traversal of the list is atomic, i.e that no-one tries to insert or
+ *    remove frames from the list while we travers it!
+ * 
+ *    FIXME: It is not safe to traverse a this list without locking it!
+ */
+void irlap_resend_rejected_frames( struct irlap_cb *self, int command) 
+{
+	struct sk_buff *tx_skb;
+	struct sk_buff *skb;
+	int count;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	DEBUG( 4, __FUNCTION__ "(), retry_count=%d\n",
+	       self->retry_count);
+
+	/* Initialize variables */
+	skb = tx_skb = NULL;
+
+	/* 
+	 *  Resend all unacknowledged frames 
+	 */
+	count = skb_queue_len( &self->wx_list);
+	skb = skb_peek( &self->wx_list);
+	while ( skb != NULL) {
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+
+		tx_skb = skb_clone( skb, GFP_ATOMIC);
+		/* tx_skb = skb_copy( skb, GFP_ATOMIC); */
+		if ( tx_skb == NULL) {
+			/* Unlink tx_skb from list */
+			tx_skb->next = tx_skb->prev = NULL;
+			tx_skb->list = NULL;
+		
+			dev_kfree_skb( skb);
+			return;	
+		}
+		/* Unlink tx_skb from list */
+		tx_skb->next = tx_skb->prev = NULL;
+		tx_skb->list = NULL;
+
+		/*
+		 *  make sure the skb->sk accounting of memory usage is sane
+		 */
+		if ( skb->sk != NULL)
+			skb_set_owner_w( tx_skb, skb->sk);
+
+		/* Clear old Nr field + poll bit */
+		tx_skb->data[1] &= 0x0f;
+
+		/* 
+		 *  Set poll bit on the last frame retransmitted
+		 */
+	 	if ( count-- == 1) 
+	 		tx_skb->data[1] |= PF_BIT; /* Set p/f bit */
+		else
+			tx_skb->data[1] &= ~PF_BIT; /* Clear p/f bit */
+	      	
+		irlap_send_i_frame( self, tx_skb, command);
+
+		/* 
+		 *  If our skb is the last buffer in the list, then
+		 *  we are finished, if not, move to the next sk-buffer
+		 */
+		if ( skb == skb_peek_tail( &self->wx_list))
+			skb = NULL;
+		else
+			skb = skb->next;
+	}
+	/* 
+	 *  We can now fill the window with additinal data frames
+	 */
+	return; /* Skip this for now, DB */
+
+	while ( skb_queue_len( &self->tx_list) > 0) {
+		
+		DEBUG( 0, "irlap_resend_rejected_frames: "
+		       "sending additional frames!\n");
+		if (( skb_queue_len( &self->tx_list) > 0) && 
+		    ( self->window > 0)) {
+			skb = skb_dequeue( &self->tx_list); 
+			ASSERT( skb != NULL, return;);
+
+			/*
+			 *  If send window > 1 then send frame with pf 
+			 *  bit cleared
+			 */ 
+			if (( self->window > 1) && 
+			    skb_queue_len( &self->tx_list) > 0) 
+			{
+				irlap_send_data_primary( self, skb);
+			} else {
+				irlap_send_data_primary_poll( self, skb);
+			}
+		}
+	}
+}
+
+/*
+ * Function irlap_send_ui_frame (self, skb, command)
+ *
+ *    Contruct and transmit an Unnumbered Information (UI) frame
+ *
+ */
+void irlap_send_ui_frame( struct irlap_cb *self, struct sk_buff *skb, 
+			  int command) 
+{
+	__u8  *frame;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	
+	frame = skb->data;
+	
+	/* Insert connection address */
+	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++;
+}
+
+/*
+ * Function irlap_send_i_frame (skb)
+ *
+ *    Contruct and transmit Information (I) frame
+ */
+void irlap_send_i_frame( struct irlap_cb *self, struct sk_buff *skb, 
+			 int command) 
+{
+	__u8  *frame;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	frame = skb->data;
+	
+	/* Insert connection address */
+	frame[0] = self->caddr;
+	frame[0] |= (command) ? CMD_FRAME : 0;
+	
+	/* Insert next to receive (Vr) */
+	frame[1] |= (self->vr << 5);  /* insert nr */
+
+#if 0	
+	{
+		int vr, vs, pf;
+		
+		/* Chech contents of various fields */
+		vr = frame[1] >> 5;
+		vs = (frame[1] >> 1) & 0x07;
+		pf = (frame[1] >> 4) & 0x01;
+		
+		DEBUG( 4, __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++;
+}
+
+/*
+ * Function irlap_recv_i_frame (skb, frame)
+ *
+ *    Receive and parse an I (Information) frame
+ * 
+ */
+static void irlap_recv_i_frame( struct irlap_cb *self, struct sk_buff *skb, 
+				struct irlap_info *info, int command) 
+{
+	__u8 *frame;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	frame = skb->data;
+
+	info->nr = frame[1] >> 5;          /* Next to receive */
+	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); 
+
+	/*
+	 *  Make sure the state-machine is in the right state for receiving, 
+	 *  if not, then we just discard the received frame for now!
+	 *  TODO: check if we should queue this frame, or make tty tell that
+	 *  it is receiving frames until the frame is delivered instead of
+	 *  until it is outside a frame.
+	 */
+	if (( self->state != LAP_NRM_P) && ( self->state != LAP_NRM_S)) {
+		DEBUG( 0, __FUNCTION__ "(), Wrong state, dropping frame!\n");
+		dev_kfree_skb( skb);
+		return;
+	}
+
+	/* Check if this is a command or a response frame */
+	if ( command)
+		irlap_do_event( self, RECV_I_CMD, skb, info);
+	else
+		irlap_do_event( self, RECV_I_RSP, skb, info);
+}
+
+/*
+ * Function irlap_recv_ui_frame (self, skb, info)
+ *
+ *    Receive and parse an Unnumbered Information (UI) frame
+ *
+ */
+static void irlap_recv_ui_frame( struct irlap_cb *self, struct sk_buff *skb, 
+				 struct irlap_info *info)
+{
+	__u8 *frame;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	frame = skb->data;
+
+	info->pf = frame[1] & PF_BIT;      /* Final bit */
+
+	irlap_do_event( self, RECV_UI_FRAME, skb, info);
+}
+
+/*
+ * Function irlap_recv_frmr_frame (skb, frame)
+ *
+ *    Received Frame Reject response.
+ *
+ */
+static void irlap_recv_frmr_frame( struct irlap_cb *self, struct sk_buff *skb, 
+				   struct irlap_info *info) 
+{
+	__u8 *frame;
+	int w, x, y, z;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( info != NULL, return;);
+	
+	frame = skb->data;
+
+	info->nr = frame[2] >> 5;          /* Next to receive */
+	info->pf = frame[2] & PF_BIT;        /* Final bit */
+	info->ns = (frame[2] >> 1) & 0x07; /* Next to send */
+
+	w = frame[3] & 0x01;
+	x = frame[3] & 0x02;
+	y = frame[3] & 0x04;
+	z = frame[3] & 0x08;
+	
+	if ( w) {
+		DEBUG( 0, "Rejected control field is undefined or not "
+		       "implemented.\n");
+	} 
+	if ( x) {
+		DEBUG( 0, "Rejected control field was invalid because it "
+		       "contained a non permitted I field.\n");
+	}
+	if ( y) {
+		DEBUG( 0, "Received I field exceeded the maximum negotiated "
+		       "for the existing connection or exceeded the maximum "
+		       "this station supports if no connection exists.\n");
+	}
+	if ( z) {
+		DEBUG( 0, "Rejected control field control field contained an "
+		       "invalid Nr count.\n");
+	}
+	irlap_do_event( self, RECV_FRMR_RSP, skb, info);
+}
+
+/*
+ * Function irlap_input (skb)
+ *
+ *  Called when a frame is received. Dispatches the right receive function 
+ *  for processing of the frame.
+ */
+int irlap_input( struct sk_buff *skb, struct device *netdev, 
+		 struct packet_type *ptype)
+{
+	struct irlap_info info;
+	struct irlap_cb *self;
+	struct irda_device *idev;
+	__u8 *frame;
+	int i, command;
+	__u8 control;
+	
+	idev = ( struct irda_device *) netdev->priv;
+
+	ASSERT( idev != NULL, return -1;);
+	self = idev->irlap;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == LAP_MAGIC, return -1;);
+	ASSERT(( skb != NULL) && (skb->len > 1), return -1;);
+	
+	frame = skb->data;
+
+	command    = frame[0] & CMD_FRAME;
+	info.caddr = frame[0] & CBROADCAST;
+	
+	info.pf      = frame[1] &  PF_BIT;
+	info.control = frame[1] & ~PF_BIT; /* Mask away poll/final bit */
+
+	control = info.control;
+
+	/* 
+	 *  First check if this frame addressed to us 
+	 */
+	if (( info.caddr != self->caddr) && ( info.caddr != CBROADCAST)) {
+
+		DEBUG( 0, __FUNCTION__ "(), Received frame is not for us!\n");
+		for(i=0; i<(skb->len < 15?skb->len:15);i++) {
+ 			printk( "%02x ", frame[i]);
+		}
+ 		printk("\n"); 
+		
+		dev_kfree_skb( skb);
+
+		return 0;
+	}
+	/*  
+	 *  Optimize for the common case and check if the frame is an
+	 *  I(nformation) frame. Only I-frames have bit 0 set to 0
+	 */
+	if( ~control & 0x01) {
+		irlap_recv_i_frame( self, skb, &info, command);
+		self->stats.rx_packets++;
+		return 0;
+	}
+	/*
+	 *  We now check is the frame is an S(upervisory) frame. Only 
+	 *  S-frames have bit 0 set to 1 and bit 1 set to 0
+	 */
+	if ( ~control & 0x02) {
+		/* 
+		 *  Received S(upervisory) frame, check which frame type it is
+		 *  only the first nibble is of interest
+		 */
+		switch( control & 0x0f) {
+		case RR:
+			irlap_recv_rr_frame( self, skb, &info, command);
+			self->stats.rx_packets++;
+			break;
+		case RNR:
+			DEBUG( 3, "*** RNR frame received! pf = %d ***\n", 
+			       info.pf >> 4);
+			irlap_recv_rnr_frame( self, skb, &info);
+			self->stats.rx_packets++;
+			break;
+		case REJ:
+			DEBUG( 0, "*** REJ frame received! ***\n");
+			break;
+		case SREJ:
+			DEBUG( 0, "*** SREJ frame received! ***\n");
+			break;
+		default:
+			DEBUG( 0, "Unknown S frame %02x received!\n", 
+			       info.control);
+			break;
+		}
+		return 0;
+	}
+	/* 
+	 *  This must be a C(ontrol) frame 
+	 */
+	switch( control) {
+	case XID_RSP:
+		DEBUG( 4, "XID rsp frame received!\n");
+		irlap_recv_discovery_xid_rsp( self, skb, &info);
+		break;
+	case XID_CMD:
+		DEBUG( 4, "XID cmd frame received!\n");
+		irlap_recv_discovery_xid_cmd( self, skb, &info);
+		break;
+	case SNRM_CMD:
+		DEBUG( 4, "SNRM frame received!\n"); 
+		irlap_recv_snrm_cmd( self, skb, &info);
+		break;
+	case DM_RSP:
+		DEBUG( 0, "DM rsp frame received!\n");
+		irlap_next_state( self, LAP_NDM);
+		break;
+	case DISC_CMD:
+		DEBUG( 0, "DISC cmd frame received!\n");
+		irlap_do_event( self, RECV_DISC_FRAME, skb, &info);
+		break;
+	case TEST_CMD:
+		DEBUG( 0, "Test frame received!\n");
+		dev_kfree_skb( skb);
+		break;
+	case UA_RSP:
+		DEBUG( 4, "UA rsp frame received!\n");
+		irlap_recv_ua_frame( self, skb, &info);
+		break;
+	case FRMR_RSP:
+		DEBUG( 4, "FRMR_RSP recevied!\n");
+		irlap_recv_frmr_frame( self, skb, &info);
+		break;
+	case UI_FRAME:
+		DEBUG( 4, "UI-frame received!\n");
+		irlap_recv_ui_frame( self, skb, &info);
+		break;
+	default:
+		DEBUG( 0, "Unknown frame %02x received!\n", info.control);
+		dev_kfree_skb( skb); 
+		break;
+	}
+	self->stats.rx_packets++;
+
+	return 0;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.1.131/linux/net/irda/irlmp.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlmp.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1341 @@
+/*********************************************************************
+ *                
+ * Filename:      irlmp.c
+ * Version:       0.8
+ * Description:   IrDA Link Management Protocol (LMP) layer                 
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun Aug 17 20:54:32 1997
+ * Modified at:   Mon Dec 14 11:54:08 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/config.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/skbuff.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/timer.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irlmp_frame.h>
+#include <linux/kmod.h>
+
+/* Master structure */
+struct irlmp_cb *irlmp = NULL;
+
+int sysctl_discovery = 0;
+char sysctl_devname[65];
+
+__u8 *irlmp_hint_to_service( __u8 *hint);
+#ifdef CONFIG_PROC_FS
+int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
+		     int unused);
+#endif
+
+/*
+ * Function irlmp_init (void)
+ *
+ *    Create (allocate) the main IrLMP structure and the pointer array
+ *    which will contain pointers to each instance of a LSAP.
+ */
+__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);
+		if ( irlmp == NULL)
+			return -ENOMEM;
+	}
+	memset( irlmp, 0, sizeof(struct irlmp_cb));
+	
+	irlmp->magic = LMP_MAGIC;
+
+	irlmp->registry = hashbin_new( HB_LOCAL);
+	irlmp->links = hashbin_new( HB_LOCAL);
+	irlmp->unconnected_lsaps = hashbin_new( HB_GLOBAL);
+	
+	irlmp->free_lsap_sel = 0x10; /* Servers use 0x00-0x0f */
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+	irlmp->cache.valid = FALSE;
+#endif
+	strcpy( sysctl_devname, "Linux");
+	
+	/* Do discovery every 3 seconds */
+	init_timer( &irlmp->discovery_timer);
+   	irlmp_start_discovery_timer( irlmp, 600); 
+
+	return 0;
+}
+
+/*
+ * Function irlmp_cleanup (void)
+ *
+ *    Remove IrLMP layer
+ *
+ */
+void irlmp_cleanup(void) 
+{
+	/* Check for main structure */
+	ASSERT( irlmp != NULL, return;);
+	ASSERT( irlmp->magic == LMP_MAGIC, return;);
+
+	del_timer( &irlmp->discovery_timer);
+	
+	/* FIXME, we need a special function to deallocate LAPs */
+	hashbin_delete( irlmp->links, (FREE_FUNC) kfree);
+	hashbin_delete( irlmp->unconnected_lsaps, (FREE_FUNC) kfree);
+	hashbin_delete( irlmp->registry, (FREE_FUNC) kfree);
+	
+	/* De-allocate main structure */
+	kfree( irlmp);
+	irlmp = NULL;
+}
+
+/*
+ * Function irlmp_open_lsap (slsap, notify)
+ *
+ *   Register with IrLMP and create a local LSAP,
+ *   returns handle to LSAP.
+ */
+struct lsap_cb *irlmp_open_lsap( __u8 slsap_sel, struct notify_t *notify)
+{
+	struct lsap_cb *self;
+
+	ASSERT( notify != NULL, return NULL;);
+	ASSERT( irlmp != NULL, return NULL;);
+	ASSERT( irlmp->magic == LMP_MAGIC, return NULL;);
+
+	DEBUG( 4, "irlmp_open_lsap(), slsap_sel=%02x\n", slsap_sel);
+
+	/* 
+	 *  Does the client care which Source LSAP selector it gets? 
+	 */
+	if ( slsap_sel == LSAP_ANY) {
+		/*
+		 *  Find unused LSAP
+		 */
+		slsap_sel = irlmp_find_free_slsap();
+		if ( slsap_sel == 0)
+			return NULL;
+	} else {
+		/*
+		 *  Client wants specific LSAP, so check if it's already
+		 *  in use
+		 */
+		if ( irlmp_slsap_inuse( slsap_sel)) {
+			return NULL;
+		}
+		if ( slsap_sel > irlmp->free_lsap_sel)
+			irlmp->free_lsap_sel = slsap_sel+1;
+	}
+
+	/*
+	 *  Allocate new instance of a LSAP connection
+	 */
+	self = kmalloc( sizeof(struct lsap_cb), GFP_ATOMIC);
+	if ( self == NULL) {
+		printk( KERN_ERR "IrLMP: Can't allocate memory for "
+			"LSAP control block!\n");
+		return NULL;
+	}
+	memset( self, 0, sizeof(struct lsap_cb));
+	
+	self->magic = LMP_LSAP_MAGIC;
+	self->slsap_sel = slsap_sel;
+	self->dlsap_sel = LSAP_ANY;
+
+	init_timer( &self->watchdog_timer);
+
+	ASSERT( notify->instance != NULL, return NULL;);
+	self->notify = *notify;
+
+	irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+	
+	/*
+	 *  Insert into queue of unconnected LSAPs
+	 */
+	hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) self, 
+			self->slsap_sel, NULL);
+	
+	return self;
+}
+
+/*
+ * Function irlmp_close_lsap (self)
+ *
+ *    Remove an instance of a LSAP
+ */
+static void __irlmp_close_lsap( struct lsap_cb *self)
+{
+	DEBUG( 4, "irlmp_close()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	/*
+	 *  Set some of the variables to preset values
+	 */
+	self->magic = ~LMP_LSAP_MAGIC;
+	del_timer( &self->watchdog_timer); /* Important! */
+
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+	ASSERT( irlmp != NULL, return;);
+	irlmp->cache.valid = FALSE;
+#endif
+	/*
+	 *  Deallocate structure
+	 */
+	kfree( self);
+
+	DEBUG( 4, "irlmp_close() -->\n");
+}
+
+/*
+ * Function irlmp_close_lsap (self)
+ *
+ *    
+ *
+ */
+void irlmp_close_lsap( struct lsap_cb *self)
+{
+	struct lap_cb *lap;
+	struct lsap_cb *lsap;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	lap = self->lap;
+
+	/*
+	 *  Find out if we should remove this LSAP from a link or from the
+	 *  list of unconnected lsaps (not associated with a link)
+	 */
+	if ( lap == NULL) {
+		lsap = hashbin_remove( irlmp->unconnected_lsaps, 
+				       self->slsap_sel, NULL);
+	} else {
+		ASSERT( lap != NULL, return;);
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
+		
+		lsap = hashbin_remove( lap->lsaps, self->slsap_sel, NULL);
+	}
+	if ( lsap == NULL) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Looks like somebody has removed me already!\n");
+		return;
+	}
+	ASSERT( lsap == self, return;);
+
+	__irlmp_close_lsap( self);
+}
+
+/*
+ * Function irlmp_register_irlap (saddr, notify)
+ *
+ *    Register IrLAP layer with IrLMP. There is possible to have multiple
+ *    instances of the IrLAP layer, each connected to different IrDA ports
+ *
+ */
+void irlmp_register_irlap( struct irlap_cb *irlap, __u32 saddr, 
+			   struct notify_t *notify)
+{
+	struct lap_cb *lap;
+
+	DEBUG( 4, __FUNCTION__ "(), Registered IrLAP, saddr = %08x\n",
+	       saddr);
+	
+	ASSERT( irlmp != NULL, return;);
+	ASSERT( irlmp->magic == LMP_MAGIC, return;);
+	ASSERT( notify != NULL, return;);
+
+	/*
+	 *  Allocate new instance of a LSAP connection
+	 */
+	lap = kmalloc( sizeof(struct lap_cb), GFP_KERNEL);
+	if ( lap == NULL) {
+		printk( KERN_ERR "IrLMP: Can't allocate memory for "
+			"LAP control block!\n");
+		return;
+	}
+	memset( lap, 0, sizeof(struct lap_cb));
+	
+	lap->irlap = irlap;
+	lap->magic = LMP_LAP_MAGIC;
+	lap->saddr = saddr;
+	lap->lsaps = hashbin_new( HB_GLOBAL);
+ 	lap->cachelog = hashbin_new( HB_LOCAL);
+
+	irlmp_next_lap_state( lap, LAP_STANDBY);
+	
+	/*
+	 *  Insert into queue of unconnected LSAPs
+	 */
+	hashbin_insert( irlmp->links, (QUEUE *) lap, lap->saddr, NULL);
+
+	/* 
+	 *  We set only this variable so IrLAP can tell us on which link the
+	 *  different events happened on 
+	 */
+	irda_notify_init( notify);
+	notify->instance = lap;
+}
+
+/*
+ * Function irlmp_unregister_irlap (saddr)
+ *
+ *    IrLAP layer has been removed!
+ *
+ */
+void irlmp_unregister_irlap( __u32 saddr)
+{
+	struct lap_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	self = hashbin_remove( irlmp->links, saddr, NULL);
+	if ( self != NULL) {
+		ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+
+		self->magic = ~LMP_LAP_MAGIC;
+		kfree( self);
+	} else {
+		DEBUG( 0, "irlmp_unregister_irlap(), Didn't find LAP!\n");
+	}
+}
+
+void dump_discoveries( hashbin_t *log)
+{
+	DISCOVERY *d;
+
+	ASSERT( log != NULL, return;);
+
+	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);
+
+		d = (DISCOVERY *) hashbin_get_next( log);
+	}
+}
+
+/*
+ * 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) 
+{
+	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;);
+	
+	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");
+		
+		return;
+	}
+
+	/* Any userdata? */
+	if ( userdata == NULL) {
+		skb = dev_alloc_skb( 64);
+		if (skb == NULL) {
+			DEBUG( 0, "irlmp_connect_request: "
+			       "Could not allocate an sk_buff of length %d\n",
+			       64);
+			return;
+		}
+		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;);
+	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);
+	
+	/* 
+	 *  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;);
+
+	hashbin_insert( self->lap->lsaps, (QUEUE *) self, self->slsap_sel, 
+			NULL);
+
+	self->connected = TRUE;
+
+	/*
+	 *  User supplied qos specifications?
+	 */
+	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);
+}
+
+/*
+ * Function irlmp_connect_indication (self)
+ *
+ *    Incomming connection
+ *
+ */
+void irlmp_connect_indication( struct lsap_cb *self, struct sk_buff *skb) 
+{
+	int max_seg_size;
+
+	DEBUG( 4, "irlmp_connect_indication()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( self->lap != NULL, return;);
+
+	self->qos = *self->lap->qos;
+
+	max_seg_size = self->lap->qos->data_size.value;
+	DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	
+	/* Hide LMP_CONTROL_HEADER header from layer above */
+	skb_pull( skb, LMP_CONTROL_HEADER);
+
+	if ( self->notify.connect_indication)
+		self->notify.connect_indication( self->notify.instance, self, 
+						 &self->qos, max_seg_size, 
+						 skb);
+}
+
+/*
+ * Function irlmp_connect_response (handle, userdata)
+ *
+ *    Service user is accepting connection
+ *
+ */
+void irlmp_connect_response( struct lsap_cb *self, struct sk_buff *userdata) 
+{
+	DEBUG( 4, "irlmp_connect_response()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( userdata != NULL, return;);
+
+	self->connected = TRUE;
+
+	DEBUG( 4, "irlmp_connect_response: slsap_sel=%02x, dlsap_sel=%02x\n", 
+	       self->slsap_sel, self->dlsap_sel);
+
+	/* Make room for MUX control header ( 3 bytes) */
+	ASSERT( skb_headroom( userdata) >= LMP_CONTROL_HEADER, return;);
+	skb_push( userdata, LMP_CONTROL_HEADER);
+	
+	irlmp_do_lsap_event( self, LM_CONNECT_RESPONSE, userdata);
+}
+
+/*
+ * Function irlmp_connect_confirm (handle, skb)
+ *
+ *    LSAP connection confirmed peer device!
+ */
+void irlmp_connect_confirm( struct lsap_cb *self, struct sk_buff *skb) 
+{
+	int max_seg_size;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( skb != NULL, return;);
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	
+	ASSERT( self->lap != NULL, return;);
+	self->qos = *self->lap->qos;
+
+	max_seg_size = self->qos.data_size.value;
+	DEBUG( 4, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
+	
+	/* Hide LMP_CONTROL_HEADER header from layer above */
+	skb_pull( skb, LMP_CONTROL_HEADER);
+
+	if ( self->notify.connect_confirm) {
+		self->notify.connect_confirm( self->notify.instance, self,
+					      &self->qos, max_seg_size, skb);
+	}
+}
+
+/*
+ * Function irlmp_disconnect_request (handle, userdata)
+ *
+ *    The service user is requesting disconnection, this will not remove the 
+ *    LSAP, but only mark it as disconnected
+ */
+void irlmp_disconnect_request( struct lsap_cb *self, struct sk_buff *userdata) 
+{
+	struct lsap_cb *lsap;
+
+	DEBUG( 4, "irlmp_disconnect_request()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	/* Already disconnected? */
+	if ( !self->connected) {
+		DEBUG( 0, __FUNCTION__ "(), already disconnected!\n");
+		return;
+	}
+
+	ASSERT( userdata != NULL, return;);
+	ASSERT( self->connected == TRUE, return;);
+	
+	skb_push( userdata, LMP_CONTROL_HEADER);
+
+	/* 
+	 *  Do the event before the other stuff since we must know
+	 *  which lap layer that the frame should be transmitted on
+	 */
+	irlmp_do_lsap_event( self, LM_DISCONNECT_REQUEST, userdata);
+
+	/* 
+	 *  Remove LSAP from list of connected LSAPs for the particular link
+	 *  and insert it into the list of unconnected LSAPs
+	 */
+	ASSERT( self->lap != NULL, return;);
+	ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( self->lap->lsaps != NULL, return;);
+
+	lsap = hashbin_remove( self->lap->lsaps, self->slsap_sel, NULL);
+
+	ASSERT( lsap != NULL, return;);
+	ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( lsap == self, return;);
+
+	hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) self, 
+			self->slsap_sel, NULL);
+	
+	/* Reset some values */
+	self->connected = FALSE;
+	self->dlsap_sel = LSAP_ANY;
+	self->lap = NULL;
+}
+
+/*
+ * Function irlmp_disconnect_indication (reason, userdata)
+ *
+ *    LSAP is being closed!
+ */
+void irlmp_disconnect_indication( struct lsap_cb *self, LM_REASON reason, 
+				  struct sk_buff *userdata) 
+{
+	struct lsap_cb *lsap;
+
+	DEBUG( 4, "irlmp_disconnect_indication()\n");	
+
+	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", 
+	       self->slsap_sel, self->dlsap_sel);
+
+	self->connected = FALSE;
+	self->dlsap_sel = LSAP_ANY;
+
+	/* 
+	 *  Remove assosiation betwen this LSAP and the kink it used 
+	 */
+	ASSERT( self->lap != NULL, return;);
+	ASSERT( self->lap->lsaps != NULL, return;);
+
+	lsap = hashbin_remove( self->lap->lsaps, self->slsap_sel, NULL);
+
+	ASSERT( lsap != NULL, return;);
+	ASSERT( lsap == self, return;);
+	hashbin_insert( irlmp->unconnected_lsaps, (QUEUE *) lsap, 
+			lsap->slsap_sel, NULL);
+
+	self->lap = NULL;
+
+	/* FIXME: the reasons should be extracted somewhere else? */
+	if ( userdata) {
+		DEBUG( 4, "irlmp_disconnect_indication: reason=%02x\n", 
+		       userdata->data[3]);
+	}
+
+	/*
+	 *  Inform service user
+	 */
+	if ( self->notify.disconnect_indication) {
+		self->notify.disconnect_indication( self->notify.instance, 
+						    self, reason, userdata);
+	}
+}
+
+/*
+ * Function irlmp_discovery_request (nslots)
+ *
+ *    Do a discovery of devices in front of the computer
+ *
+ */
+void irlmp_discovery_request( int nslots)
+{
+	struct lap_cb *lap;
+
+	DEBUG( 4, "irlmp_discovery_request()\n");
+
+	ASSERT( irlmp != NULL, return;);
+
+	if ( !sysctl_discovery)
+		return;
+
+	/*
+	 *  Construct new discovery info to be used by IrLAP,
+	 *  TODO: no need to do this every time!
+	 */
+	irlmp->discovery_cmd.hint[0] = irlmp->hint[0];
+	irlmp->discovery_cmd.hint[1] = irlmp->hint[1];
+	
+	/* 
+	 *  Set character set for device name (we use ASCII), and 
+	 *  copy device name. Remember to make room for a \0 at the 
+	 *  end
+	 */
+	irlmp->discovery_cmd.charset = CS_ASCII;
+	
+	strncpy( irlmp->discovery_cmd.info, sysctl_devname, 31);
+	irlmp->discovery_cmd.info_len = strlen( irlmp->discovery_cmd.info);
+	
+	/*
+	 * Try to send discovery packets on all links
+	 */
+	lap = ( struct lap_cb *) hashbin_get_first( irlmp->links);
+	while ( lap != NULL) {
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
+
+		DEBUG( 4, "irlmp_discovery_request() sending request!\n");
+		irlmp_do_lap_event( lap, LM_LAP_DISCOVERY_REQUEST, NULL);
+		
+		lap = ( struct lap_cb *) hashbin_get_next( irlmp->links);
+	}
+}
+
+/*
+ * Function irlmp_check_services (discovery)
+ *
+ *    
+ *
+ */
+void irlmp_check_services( DISCOVERY *discovery) 
+{
+	struct irlmp_registration *entry;
+	struct irmanager_event event;
+	__u8 *service;
+	int i = 0;
+
+	printk( KERN_INFO "IrDA Discovered: %s\n", discovery->info);
+	printk( KERN_INFO "    Services: ");
+
+
+	service = irlmp_hint_to_service( discovery->hint);
+	if (service != NULL) {
+		/*
+		 *  Check all services on the device
+		 */
+		while ( service[i] != S_END) {
+			DEBUG( 4, "service=%02x\n", service[i]);
+			entry = hashbin_find( irlmp->registry, 
+					      service[i], NULL);
+			if ( entry && entry->discovery_callback) {
+				DEBUG( 4, "discovery_callback!\n");
+					entry->discovery_callback( discovery);
+			} else {
+				/* 
+				 * Found no clients for dealing with this
+				 * service, so ask the user space irmanager
+				 * to try to load the right module for us
+				 */
+
+				event.event = EVENT_DEVICE_DISCOVERED;
+				event.service = service[i];
+				event.daddr = discovery->daddr;
+				sprintf( event.info, "%s", 
+					 discovery->info);
+				irmanager_notify( &event);
+			}
+			i++; /* Next service */
+		}
+		kfree( service);
+	}
+}
+
+/*
+ * Function irlmp_discovery_confirm ( self, log)
+ *
+ *    Some device(s) answered to our discovery request! Check to see which
+ *    device it is, and give indication to the client(s)
+ * 
+ */
+void irlmp_discovery_confirm( struct lap_cb *self, hashbin_t *log) 
+{
+	DISCOVERY *discovery;
+	
+	DEBUG( 4, "irlmp_discovery_confirm()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+
+	/*
+	 *  If log is missing this means that IrLAP was unable to perform the
+	 *  discovery, so restart discovery again with just the half timeout
+	 *  of the normal one.
+	 */
+	if ( !log) {
+		irlmp_start_discovery_timer( irlmp, 150);
+		return;
+	}
+
+	/*
+	 *  Now, check all discovered devices (if any)
+	 */
+	discovery = ( DISCOVERY *) hashbin_get_first( log);
+	while ( discovery != NULL) {
+		self->daddr = discovery->daddr;
+
+		DEBUG( 4, "discovery->daddr = 0x%08x\n", discovery->daddr); 
+		
+		irlmp_check_services( discovery);
+
+		discovery = ( DISCOVERY *) hashbin_get_next( log);
+	}
+}
+
+/*
+ * Function irlmp_discovery_indication (discovery)
+ *
+ *    A remote device is discovering us!
+ *
+ */
+void irlmp_discovery_indication( struct lap_cb *self, DISCOVERY *discovery)
+{
+	/* struct irda_event event; */
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( discovery != NULL, return;);
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	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);
+	/*
+	 *  Insert this discovery device into the discovery_log if its
+	 *  not there already
+	 */
+	if ( !hashbin_find( self->cachelog, discovery->daddr, NULL))
+		hashbin_insert( self->cachelog, (QUEUE *) discovery,
+				discovery->daddr, NULL);
+
+	irlmp_check_services( discovery);
+}
+
+/*
+ * Function irlmp_get_discovery_response ()
+ *
+ *    Used by IrLAP to get the disocvery info it needs when answering
+ *    discovery requests by other devices.
+ */
+DISCOVERY *irlmp_get_discovery_response()
+{
+	DEBUG( 4, "irlmp_get_discovery_response()\n");
+
+	ASSERT( irlmp != NULL, return NULL;);
+
+	irlmp->discovery_rsp.hint[0] = irlmp->hint[0];
+	irlmp->discovery_rsp.hint[1] = irlmp->hint[1];
+
+	/* 
+	 *  Set character set for device name (we use ASCII), and 
+	 *  copy device name. Remember to make room for a \0 at the 
+	 *  end
+	 */
+	irlmp->discovery_rsp.charset = CS_ASCII;
+
+	strncpy( irlmp->discovery_rsp.info, sysctl_devname, 31);
+	irlmp->discovery_rsp.info_len = strlen( irlmp->discovery_rsp.info) + 2;
+
+	return &irlmp->discovery_rsp;
+}
+
+/*
+ * Function irlmp_data_request (self, skb)
+ *
+ *    Send some data to peer device
+ *
+ */
+void irlmp_data_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;);
+	skb_push( skb, LMP_HEADER);
+
+	irlmp_do_lsap_event( self, LM_DATA_REQUEST, skb);
+}
+
+/*
+ * Function irlmp_data_indication (handle, skb)
+ *
+ *    Got data from LAP layer so pass it up to upper layer
+ *
+ */
+void irlmp_data_indication( struct lsap_cb *self, struct sk_buff *skb) 
+{
+ 	DEBUG( 4, "irlmp_data_indication()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	/* Hide LMP header from layer above */
+	skb_pull( skb, LMP_HEADER);
+
+	if ( self->notify.data_indication)
+		self->notify.data_indication(self->notify.instance, self, skb);
+}
+
+/*
+ * Function irlmp_udata_request (self, skb)
+ *
+ *    
+ *
+ */
+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;);
+	skb_push( skb, LMP_HEADER);
+
+	irlmp_do_lsap_event( self, LM_UDATA_REQUEST, skb);
+}
+
+/*
+ * Function irlmp_udata_indication (self, skb)
+ *
+ *    Send unreliable data (but still within the connection)
+ *
+ */
+void irlmp_udata_indication( struct lsap_cb *self, struct sk_buff *skb) 
+{
+ 	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	/* Hide LMP header from layer above */
+	skb_pull( skb, LMP_HEADER);
+
+	if ( self->notify.udata_indication)
+		self->notify.udata_indication( self->notify.instance, self, 
+					      skb);
+}
+
+/*
+ * Function irlmp_connection_less_data_request (skb)
+ *
+ *    Send out of connection UI frames
+ *
+ */
+void irlmp_connectionless_data_request( struct sk_buff *skb)
+{
+	DEBUG( 0, __FUNCTION__ "()\n"); 
+}
+
+/*
+ * Function irlmp_connection_less_data_indication (skb)
+ *
+ *    
+ *
+ */
+void irlmp_connectionless_data_indication( struct sk_buff *skb)
+{
+	DEBUG( 0, __FUNCTION__ "()\n"); 
+}
+
+void irlmp_status_request(void) 
+{
+	DEBUG( 0, "irlmp_status_request(), Not implemented\n");
+}
+
+void irlmp_status_indication( LINK_STATUS link, LOCK_STATUS lock) 
+{
+	DEBUG( 4, "irlmp_status_indication(), Not implemented\n");
+}
+
+/*
+ * Function irlmp_hint_to_service (hint)
+ *
+ *    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 *service;
+	int i = 0;
+
+	/* Allocate array to store services in */
+	service = kmalloc( 16, GFP_ATOMIC);
+	if ( !service) {
+		DEBUG( 0, "irlmp_hint_to_service: Unable to kmalloc!\n");
+		return NULL;
+	}
+
+	if ( !hint[0]) {
+		printk( "<None>\n");
+		return NULL;
+	}
+	if ( hint[0] & HINT_PNP)
+		printk( "PnP Compatible ");
+	if ( hint[0] & HINT_PDA)
+		printk( "PDA/Palmtop ");
+	if ( hint[0] & HINT_COMPUTER)
+		printk( "Computer ");
+	if ( hint[0] & HINT_PRINTER) {
+		printk( "Printer\n");
+		service[i++] = S_PRINTER;
+	}
+	if ( hint[0] & HINT_MODEM)
+		printk( "Modem ");
+	if ( hint[0] & HINT_FAX)
+		printk( "Fax ");
+	if ( hint[0] & HINT_LAN) {
+		printk( "LAN Access\n");			
+		service[i++] = S_LAN;
+	}
+	/* 
+	 *  Test if extension byte exists. This byte will usually be
+	 *  there, but this is not really required by the standard.
+	 *  (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_COMM) {
+			printk( "IrCOMM ");
+			service[i++] = S_COMM;
+		}
+		if ( hint[1] & HINT_OBEX) {
+			printk( "IrOBEX ");
+			service[i++] = S_OBEX;
+		}
+	}
+	printk( "\n");
+
+	service[i] = S_END;
+	
+	return service;
+}
+
+/*
+ * Function irlmp_service_to_hint (service, hint)
+ *
+ *    
+ *
+ */
+void irlmp_service_to_hint( int service, __u8 *hint)
+{
+	switch (service) {
+	case S_PNP:
+		hint[0] |= HINT_PNP;
+		break;
+	case S_PDA:
+		hint[0] |= HINT_PDA;
+		break;
+	case S_COMPUTER:
+		hint[0] |= HINT_COMPUTER;
+		break;
+	case S_PRINTER:
+		hint[0] |= HINT_PRINTER;
+		break;
+	case S_MODEM:
+		hint[0] |= HINT_PRINTER;
+		break;
+	case S_LAN:
+		hint[0] |= HINT_LAN;
+		break;
+	case S_COMM:
+		hint[0] |= HINT_EXTENSION;
+		hint[1] |= HINT_COMM;
+		break;
+	case S_OBEX:
+		hint[0] |= HINT_EXTENSION;
+		hint[1] |= HINT_OBEX;
+		break;
+	default:
+		DEBUG( 0, "irlmp_service_to_hint(), Unknown service!\n");
+		break;
+	}
+}
+
+/*
+ * Function irlmp_register (service, type, callback)
+ *
+ *    Register a local client or server with IrLMP
+ *
+ */
+void irlmp_register_layer( int service, int type, int do_discovery, 
+			   DISCOVERY_CALLBACK callback)
+{
+	struct irlmp_registration *entry;
+
+	sysctl_discovery |= do_discovery;
+
+	if ( type & SERVER)
+		irlmp_service_to_hint( service, irlmp->hint);
+
+	/* Check if this service has been registred before */
+	entry = hashbin_find( irlmp->registry, service, NULL);
+	if ( entry != NULL) {
+		/* Update type in entry */
+		entry->type |= type;
+
+		/*  Update callback only if client, since servers don't 
+		 *  use callbacks, and we don't want to overwrite a 
+		 *  previous registred client callback
+		 */
+		if ( type & CLIENT)
+			entry->discovery_callback = callback;
+		return;
+	}
+
+	/* Make a new registration */
+ 	entry = kmalloc( sizeof( struct irlmp_registration), GFP_ATOMIC);
+	if ( !entry) {
+		DEBUG( 0, "irlmp_register(), Unable to kmalloc!\n");
+		return;
+	}
+
+	entry->service = service;
+	entry->type = type;
+	entry->discovery_callback = callback;
+
+ 	hashbin_insert( irlmp->registry, (QUEUE*) entry, entry->service, NULL);
+}
+
+/*
+ * Function irlmp_unregister (serivice)
+ *
+ *    
+ *
+ */
+void irlmp_unregister_layer( int service, int type)
+{
+ 	struct irlmp_registration *entry;
+ 
+ 	DEBUG( 4, __FUNCTION__ "()\n");
+ 
+	entry = hashbin_find( irlmp->registry, service, NULL);
+	if ( entry != NULL) {
+		DEBUG( 4, "Found entry to change or remove!\n");
+		/* Remove this type from the service registration */
+		entry->type &= ~type;
+	}
+
+	if ( !entry) {
+		DEBUG( 0, "Unable to find entry to unregister!\n");
+		return;
+	}
+
+	/* 
+	 *  Remove entry if there is no more client and server support 
+	 *  left in entry
+	 */
+	if ( !entry->type) {
+		DEBUG( 4, __FUNCTION__ "(), removing entry!\n");
+		entry = hashbin_remove( irlmp->registry, service, NULL);
+		if ( entry != NULL)
+			kfree( entry);
+	}
+
+	/* Remove old hint bits */
+	irlmp->hint[0] = 0;
+	irlmp->hint[1] = 0;
+
+	/* Refresh current hint bits */
+        entry = (struct irlmp_registration *) hashbin_get_first( irlmp->registry);
+        while( entry != NULL) {
+		if ( entry->type & SERVER)
+			irlmp_service_to_hint( entry->service, 
+					       irlmp->hint);
+                entry = (struct irlmp_registration *) 
+			hashbin_get_next( irlmp->registry);
+        }
+}
+
+/*
+ * Function irlmp_slsap_inuse (slsap)
+ *
+ *    Check if the given source LSAP selector is in use
+ */
+int irlmp_slsap_inuse( __u8 slsap_sel)
+{
+	struct lsap_cb *self;
+	struct lap_cb *lap;
+
+	ASSERT( irlmp != NULL, return TRUE;);
+	ASSERT( irlmp->magic == LMP_MAGIC, return TRUE;);
+	ASSERT( slsap_sel != LSAP_ANY, return TRUE;);
+
+	DEBUG( 4, "irlmp_slsap_inuse()\n");
+
+	/*
+	 *  Check if slsap is already in use. To do this we have to loop over
+	 *  every IrLAP connection and check every LSAP assosiated with each
+	 *  the connection.
+	 */
+	lap = ( struct lap_cb *) hashbin_get_first( irlmp->links);
+	while ( lap != NULL) {
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return TRUE;);
+
+		self = (struct lsap_cb *) hashbin_get_first( lap->lsaps);
+		while ( self != NULL) {
+			ASSERT( self->magic == LMP_LSAP_MAGIC, return TRUE;);
+
+			if (( self->slsap_sel == slsap_sel))/*  &&  */
+/* 			    ( self->dlsap_sel == LSAP_ANY)) */
+			{
+				DEBUG( 4, "Source LSAP selector=%02x in use\n",
+				       self->slsap_sel); 
+				return TRUE;
+			}
+			self = (struct lsap_cb*) hashbin_get_next( lap->lsaps);
+		}
+		lap = (struct lap_cb *) hashbin_get_next( irlmp->links);
+	}     
+	return FALSE;
+}
+
+/*
+ * Function irlmp_find_free_slsap ()
+ *
+ *    Find a free source LSAP to use. This function is called if the service
+ *    user has requested a source LSAP equal to LM_ANY
+ */
+__u8 irlmp_find_free_slsap(void) 
+{
+	__u8 lsap_sel;
+
+	ASSERT( irlmp != NULL, return -1;);
+	ASSERT( irlmp->magic == LMP_MAGIC, return -1;);
+      
+	lsap_sel = irlmp->free_lsap_sel++;
+
+	DEBUG( 4, "irlmp_find_free_slsap(), picked next free lsap_sel=%02x\n",
+	       lsap_sel);
+
+	return lsap_sel;
+}
+
+/*
+ * Function irlmp_convert_lap_reason (lap_reason)
+ *
+ *    Converts IrLAP disconnect reason codes to IrLMP disconnect reason
+ *    codes
+ *
+ */
+LM_REASON irlmp_convert_lap_reason( LAP_REASON lap_reason)
+{
+	int reason = LM_LAP_DISCONNECT;
+
+	switch (lap_reason) {		
+	case LAP_DISC_INDICATION: /* Received a disconnect request from peer */
+		reason = LM_USER_REQUEST;
+		break;
+	case LAP_NO_RESPONSE:    /* To many retransmits without response */
+		reason = LM_LAP_DISCONNECT;
+		break;
+	case LAP_RESET_INDICATION:
+		reason = LM_LAP_RESET;
+		break;
+	case LAP_FOUND_NONE:
+	case LAP_MEDIA_BUSY:
+	case LAP_PRIMARY_CONFLICT:
+		reason = LM_CONNECT_FAILURE;
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ 
+		       "(), Unknow IrLAP disconnect reason %d!\n", lap_reason);
+		reason = LM_LAP_DISCONNECT;
+		break;
+	}
+
+	return reason;
+}	
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irlmp_proc_read (buf, start, offset, len, unused)
+ *
+ *    Give some info to the /proc file system
+ *
+ */
+int irlmp_proc_read( char *buf, char **start, off_t offset, int len, 
+		     int unused)
+{
+	struct lsap_cb *self;
+	struct lap_cb *lap;
+	unsigned long flags;
+
+	ASSERT( irlmp != NULL, return 0;);
+	
+	save_flags( flags);
+	cli();
+
+	len = 0;
+	
+	len += sprintf( buf+len, "Unconnected LSAPs:\n");
+	self = (struct lsap_cb *) hashbin_get_first( irlmp->unconnected_lsaps);
+	while ( self != NULL) {
+		ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;);
+		len += sprintf( buf+len, "lsap state: %s, ", 
+				irlsap_state[ self->lsap_state]);
+		len += sprintf( buf+len, 
+				"slsap_sel: %#02x, dlsap_sel: %#02x, ",
+				self->slsap_sel, self->dlsap_sel); 
+		len += sprintf( buf+len, "(%s)", self->notify.name);
+		len += sprintf( buf+len, "\n");
+
+		self = ( struct lsap_cb *) hashbin_get_next( 
+			irlmp->unconnected_lsaps);
+ 	} 
+
+	len += sprintf( buf+len, "\nRegistred Link Layers:\n");
+	lap = (struct lap_cb *) hashbin_get_first( irlmp->links);
+	while ( lap != NULL) {
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;);
+
+		len += sprintf( buf+len, "lap state: %s, ", 
+				irlmp_state[ lap->lap_state]);
+
+		len += sprintf( buf+len, 
+				"saddr: %#08x, daddr: %#08x, ",
+				lap->saddr, lap->daddr); 
+		len += sprintf( buf+len, "\n");
+
+		len += sprintf( buf+len, "\nConnected LSAPs:\n");
+		self = (struct lsap_cb *) hashbin_get_first( lap->lsaps);
+		while ( self != NULL) {
+			ASSERT( self->magic == LMP_LSAP_MAGIC, return 0;);
+			len += sprintf( buf+len, "lsap state: %s, ", 
+					irlsap_state[ self->lsap_state]);
+			len += sprintf( buf+len, 
+					"slsap_sel: %#02x, dlsap_sel: %#02x, ",
+					self->slsap_sel, self->dlsap_sel);
+			len += sprintf( buf+len, "(%s)", self->notify.name);
+			len += sprintf( buf+len, "\n");
+			
+			self = ( struct lsap_cb *) hashbin_get_next( 
+				lap->lsaps);
+		} 
+
+		lap = ( struct lap_cb *) hashbin_get_next( 
+			irlmp->links);
+ 	} 
+
+	restore_flags( flags);
+
+	return len;
+}
+
+#endif /* PROC_FS */
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.1.131/linux/net/irda/irlmp_event.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlmp_event.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,693 @@
+/*********************************************************************
+ *                
+ * Filename:      irlmp_event.c
+ * Version:       0.1
+ * 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:   Wed Dec  9 01:48:48 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/kernel.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/timer.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irlmp_frame.h>
+#include <net/irda/irlmp_event.h>
+
+char *irlmp_state[] = {
+	"LAP_STANDBY",
+	"LAP_U_CONNECT",
+	"LAP_ACTIVE",
+};
+
+char *irlsap_state[] = {
+	"LSAP_DISCONNECTED",
+	"LSAP_CONNECT",
+	"LSAP_CONNECT_PEND",
+	"LSAP_DATA_TRANSFER_READY",
+	"LSAP_SETUP",
+	"LSAP_SETUP_PEND",
+};
+
+static char *irlmp_event[] = {
+	"LM_CONNECT_REQUEST",
+ 	"LM_CONNECT_CONFIRM",
+	"LM_CONNECT_RESPONSE",
+ 	"LM_CONNECT_INDICATION", 	
+	
+	"LM_DISCONNECT_INDICATION",
+	"LM_DISCONNECT_REQUEST",
+
+ 	"LM_DATA_REQUEST",
+	"LM_UDATA_REQUEST",
+ 	"LM_DATA_INDICATION",
+	"LM_UDATA_INDICATION",
+
+	"LM_WATCHDOG_TIMEOUT",
+
+	/* IrLAP events */
+	"LM_LAP_CONNECT_REQUEST",
+ 	"LM_LAP_CONNECT_INDICATION", 
+ 	"LM_LAP_CONNECT_CONFIRM",
+ 	"LM_LAP_DISCONNECT_INDICATION", 
+	"LM_LAP_DISCONNECT_REQUEST",
+	"LM_LAP_DISCOVERY_REQUEST",
+ 	"LM_LAP_DISCOVERY_CONFIRM",
+};
+
+/* LAP Connection control proto declarations */
+static void irlmp_state_standby  ( struct lap_cb *, IRLMP_EVENT, 
+				   struct sk_buff *);
+static void irlmp_state_u_connect( struct lap_cb *, IRLMP_EVENT, 
+				   struct sk_buff *);
+static void irlmp_state_active   ( struct lap_cb *, IRLMP_EVENT, 
+				   struct sk_buff *);
+
+/* LSAP Connection control proto declarations */
+static void irlmp_state_disconnected( struct lsap_cb *, IRLMP_EVENT, 
+				      struct sk_buff *);
+static void irlmp_state_connect     ( struct lsap_cb *, IRLMP_EVENT, 
+				      struct sk_buff *);
+static void irlmp_state_connect_pend( struct lsap_cb *, IRLMP_EVENT,
+				      struct sk_buff *);
+static void irlmp_state_dtr         ( struct lsap_cb *, IRLMP_EVENT, 
+				      struct sk_buff *);
+static void irlmp_state_setup       ( struct lsap_cb *, IRLMP_EVENT, 
+				      struct sk_buff *);
+static void irlmp_state_setup_pend  ( struct lsap_cb *, IRLMP_EVENT, 
+				      struct sk_buff *);
+
+static void (*lap_state[]) ( struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
+{
+	irlmp_state_standby,
+	irlmp_state_u_connect,
+	irlmp_state_active,
+};
+
+static void (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
+{
+	irlmp_state_disconnected,
+	irlmp_state_connect,
+	irlmp_state_connect_pend,
+	irlmp_state_dtr,
+	irlmp_state_setup,
+	irlmp_state_setup_pend
+};
+
+/* Do connection control events */
+void irlmp_do_lsap_event( struct lsap_cb *self, IRLMP_EVENT event, 
+			  struct sk_buff *skb)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	DEBUG( 4, "do_lsap_event: EVENT = %s, STATE = %s\n",
+	       irlmp_event[ event], irlmp_state[ self->lsap_state]);
+
+	(*lsap_state[ self->lsap_state]) ( self, event, skb);
+}
+
+/*
+ * Function do_lap_event (event, skb, info)
+ *
+ *    Do IrLAP control events
+ *
+ */
+void irlmp_do_lap_event( struct lap_cb *self, IRLMP_EVENT event, 
+			 struct sk_buff *skb) 
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	
+	DEBUG( 4, "do_lap_event: EVENT = %s, STATE = %s\n",
+	       irlmp_event[event], 
+	       irlmp_state[self->lap_state]);
+
+	(*lap_state[ self->lap_state]) ( self, event, skb);
+}
+
+void irlmp_discovery_timer_expired( unsigned long data)
+{
+/* 	struct irlmp_cb *self = ( struct irlmp_cb *) data; */
+	
+	DEBUG( 4, "IrLMP, discovery timer expired!\n");
+	
+	irlmp_discovery_request( 8);
+
+	/*
+	 *  Restart timer
+	 */
+	irlmp_start_discovery_timer( irlmp, 300);
+}
+
+void irlmp_watchdog_timer_expired( unsigned long data)
+{
+	struct lsap_cb *self = ( struct lsap_cb *) data;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL);
+}
+
+/*********************************************************************
+ *
+ *    LAP connection control states
+ *
+ ********************************************************************/
+
+/*
+ * Function irlmp_state_standby (event, skb, info)
+ *
+ *    STANDBY, The IrLAP connection does not exist.
+ *
+ */
+static void irlmp_state_standby( struct lap_cb *self, IRLMP_EVENT event, 
+				 struct sk_buff *skb)
+{	
+	DEBUG( 4, "irlmp_state_standby()\n"); 
+	ASSERT( self->irlap != NULL, return;);
+	
+	switch( event) {
+	case LM_LAP_DISCOVERY_REQUEST:
+		/* irlmp_next_station_state( LMP_DISCOVER); */
+		
+		irlap_discovery_request( self->irlap, &irlmp->discovery_cmd);
+		break;
+	case LM_LAP_DISCOVERY_CONFIRM:
+ 		/* irlmp_next_station_state( LMP_READY); */
+		irlmp_discovery_confirm( self, self->cachelog);
+ 		break;
+	case LM_LAP_CONNECT_INDICATION:
+		/*  It's important to switch state first, to avoid IrLMP to 
+		 *  think that the link is free since IrLMP may then start
+		 *  discovery before the connection is properly set up. DB.
+		 */
+		irlmp_next_lap_state( self, LAP_ACTIVE);
+
+		/* Just accept connection TODO, this should be fixed */
+		irlap_connect_response( self->irlap, skb);
+		break;
+	case LM_LAP_CONNECT_REQUEST:
+		DEBUG( 4, "irlmp_state_standby() LS_CONNECT_REQUEST\n");
+
+		/* FIXME: need to set users requested QoS */
+		irlap_connect_request( self->irlap, self->daddr, NULL, 0);
+
+		irlmp_next_lap_state( self, LAP_U_CONNECT);
+		break;
+	case LM_LAP_DISCONNECT_INDICATION:
+		DEBUG( 4, __FUNCTION__ 
+		       "(), Error LM_LAP_DISCONNECT_INDICATION\n");
+		
+		irlmp_next_lap_state( self, LAP_STANDBY);
+		break;
+	default:
+		DEBUG( 4, "irlmp_state_standby: Unknown event\n");
+		break;
+	}
+}
+
+/*
+ * Function irlmp_state_u_connect (event, skb, info)
+ *
+ *    U_CONNECT, The layer above has tried to open an LSAP connection but
+ *    since the IrLAP connection does not exist, we must first start an
+ *    IrLAP connection. We are now waiting response from IrLAP.
+ * */
+static void irlmp_state_u_connect( struct lap_cb *self, IRLMP_EVENT event, 
+				   struct sk_buff *skb)
+{
+	struct lsap_cb *lsap;
+	struct lsap_cb *lsap_current;
+	
+	DEBUG( 4, "irlmp_state_u_connect()\n"); 
+
+	switch( event) {
+	case LM_LAP_CONNECT_CONFIRM:
+		/* For all lsap_ce E Associated do LS_Connect_confirm */
+		irlmp_next_lap_state( self, LAP_ACTIVE);
+
+		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
+		while ( lsap != NULL) {
+			irlmp_do_lsap_event( lsap, 
+					     LM_LAP_CONNECT_CONFIRM,
+					     skb); 
+			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
+		}		
+		break;
+	case LM_LAP_DISCONNECT_INDICATION:
+		DEBUG( 0, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+	
+		irlmp_next_lap_state( self, LAP_STANDBY);
+
+		/* Send disconnect event to all LSAPs using this link */
+		
+		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
+		while ( lsap != NULL ) {
+			ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+			
+			lsap_current = lsap;
+
+			/* Be sure to stay one item ahead */
+			lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps);
+			irlmp_do_lsap_event( lsap_current, 
+					     LM_LAP_DISCONNECT_INDICATION,
+					     NULL);
+		}
+		break;
+	case LM_LAP_DISCONNECT_REQUEST:
+		DEBUG( 0, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
+		/* irlmp_next_lap_state( self, LAP_STANDBY); */
+
+/* 		irlap_disconnect_request( self->irlap); */
+		break;
+	default:
+		DEBUG( 4, "irlmp_state_u_connect: Unknown event\n");
+		break;
+	}	
+}
+
+/*
+ * Function irlmp_state_active (event, skb, info)
+ *
+ *    ACTIVE, IrLAP connection is active
+ *
+ */
+static void irlmp_state_active( struct lap_cb *self, IRLMP_EVENT event, 
+				struct sk_buff *skb)
+{
+	struct lsap_cb *lsap;
+	struct lsap_cb *lsap_current;
+
+	DEBUG( 4, "irlmp_state_active()\n"); 
+
+ 	switch( event) {
+	case LM_LAP_CONNECT_REQUEST:
+		DEBUG( 4, "irlmp_state_active(), LS_CONNECT_REQUEST\n");
+
+		/*
+		 *  LAP connection allready active, just bounce back! Since we 
+		 *  don't know which LSAP that tried to do this, we have to 
+		 *  notify all LSAPs using this LAP, but that should be safe to
+		 *  do anyway.
+		 */
+		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);
+		}
+		
+		/* 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
+		 */
+		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);
+		}
+		break;
+	case LM_LAP_DISCONNECT_INDICATION:
+		DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+	
+		irlmp_next_lap_state( self, LAP_STANDBY);		
+		
+		/* 
+		 *  Inform all connected LSAP's using this link
+		 */
+		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
+		while ( lsap != NULL ) {
+			ASSERT( lsap->magic == LMP_LSAP_MAGIC, return;);
+			
+			lsap_current = lsap;
+
+			/* Be sure to stay one item ahead */
+			lsap = ( struct lsap_cb *) hashbin_get_next( self->lsaps);
+			irlmp_do_lsap_event( lsap_current, 
+					     LM_LAP_DISCONNECT_INDICATION,
+					     NULL);
+		}
+		break;
+	default:
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
+		break;
+	}	
+}
+
+/*********************************************************************
+ *
+ *    LSAP connection control states
+ *
+ ********************************************************************/
+
+/*
+ * Function irlmp_state_disconnected (event, skb, info)
+ *
+ *    DISCONNECTED
+ *
+ */
+static void irlmp_state_disconnected( struct lsap_cb *self, IRLMP_EVENT event,
+				      struct sk_buff *skb) 
+{
+	struct lsap_cb *lsap;
+
+	DEBUG( 4, "irlmp_state_disconnected()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	switch( event) {
+	case LM_CONNECT_REQUEST:
+		DEBUG( 4, "irlmp_state_disconnected: LM_CONNECT_REQUEST\n");
+		irlmp_next_lsap_state( self, LSAP_SETUP_PEND);
+
+		irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, NULL);
+
+		/* Start watchdog timer ( 5 secs for now) */
+		irlmp_start_watchdog_timer( self, 500);
+		break;
+	case LM_CONNECT_INDICATION:
+		irlmp_next_lsap_state( self, LSAP_CONNECT_PEND);
+
+
+		/* 
+		 *  Bind this LSAP to the IrLAP link where the connect was
+		 *  received 
+		 *  FIXME: this should be done in the LAP state machine
+		 */
+		lsap = hashbin_remove( irlmp->unconnected_lsaps, 
+				       self->slsap_sel, NULL);
+
+		ASSERT( lsap == self, return;);
+		
+		ASSERT( self->lap != NULL, return;);
+		ASSERT( self->lap->lsaps != NULL, return;);
+		
+		hashbin_insert( self->lap->lsaps, (QUEUE *) self, 
+				self->slsap_sel, NULL);
+
+		irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, skb);
+		break;
+	default:
+		/* DEBUG( 4, "irlmp_state_disconnected: Unknown event %d\n",
+		   event); */
+		break;
+	}
+}
+
+/*
+ * Function irlmp_state_connect (self, event, skb)
+ *
+ *    CONNECT
+ *
+ */
+static void irlmp_state_connect( struct lsap_cb *self, IRLMP_EVENT event, 
+				 struct sk_buff *skb) 
+{
+
+	DEBUG( 4, "irlmp_state_connect()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	switch( event) {
+	case LM_CONNECT_RESPONSE:
+		ASSERT( skb != NULL, return;);
+
+		irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, 
+				    self->slsap_sel, CONNECT_CNF, skb);
+
+		del_timer( &self->watchdog_timer);
+
+		irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
+		break;
+	default:
+		DEBUG( 4, "irlmp_state_connect: Unknown event\n");
+		break;
+	}
+}
+
+/*
+ * Function irlmp_state_connect_pend (event, skb, info)
+ *
+ *    CONNECT_PEND
+ *
+ */
+static void irlmp_state_connect_pend( struct lsap_cb *self, IRLMP_EVENT event,
+				      struct sk_buff *skb) 
+{
+	DEBUG( 4, "irlmp_state_connect_pend()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	switch( event) {
+	case LM_CONNECT_REQUEST:
+		/* Keep state */
+		break;
+	case LM_CONNECT_RESPONSE:
+		printk( KERN_WARNING 
+			"IrLMP CONNECT-PEND, No indication issued yet\n");
+		/* Keep state */
+		break;
+	case LM_DISCONNECT_REQUEST:
+		printk( KERN_WARNING
+			"IrLMP CONNECT-PEND, "
+			"Not yet bound to IrLAP connection\n");
+		/* Keep state */
+		break;
+	case LM_LAP_CONNECT_CONFIRM:
+		DEBUG( 4, "irlmp_state_connect_pend: LS_CONNECT_CONFIRM\n");
+		irlmp_next_lsap_state( self, LSAP_CONNECT);
+		irlmp_connect_indication( self, skb);
+		break;
+		
+	default:
+		DEBUG( 4, "irlmp_state_connect_pend: Unknown event %d\n", 
+		       event);
+		break;	
+	}	
+}
+
+/*
+ * Function irlmp_state_dtr (self, event, skb)
+ *
+ *    DATA_TRANSFER_READY
+ *
+ */
+static void irlmp_state_dtr( struct lsap_cb *self, IRLMP_EVENT event, 
+			     struct sk_buff *skb) 
+{
+	LM_REASON reason;
+
+ 	DEBUG( 4, "irlmp_state_dtr()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+	ASSERT( self->lap != NULL, return;);
+
+	switch( event) {
+	case LM_CONNECT_REQUEST:
+		printk( KERN_WARNING 
+			"IrLMP DTR:  Error, LSAP allready connected\n");
+		/* Keep state */
+		break;
+	case LM_CONNECT_RESPONSE:
+		printk( KERN_WARNING 
+			"IrLMP DTR:  Error, LSAP allready connected\n");
+		/* Keep state */
+		break;
+	case LM_DISCONNECT_REQUEST:
+		ASSERT( skb != NULL, return;);
+
+		irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, 
+				    self->slsap_sel, DISCONNECT, skb);
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		
+		/* Try to close the LAP connection if its still there */
+		if ( self->lap) {
+			DEBUG( 4, __FUNCTION__ "(), trying to close IrLAP\n");
+			irlmp_do_lap_event( self->lap, 
+					    LM_LAP_DISCONNECT_REQUEST, 
+					    NULL);
+		}
+
+		break;
+	case LM_DATA_REQUEST:
+		ASSERT( skb != NULL, return;);
+		irlmp_send_data_pdu( self->lap, self->dlsap_sel, 
+				     self->slsap_sel, FALSE, skb);
+		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
+		break;
+	case LM_UDATA_REQUEST:
+		ASSERT( skb != NULL, return;);
+		irlmp_send_data_pdu( self->lap, self->dlsap_sel, 
+				     self->slsap_sel, TRUE, skb);
+		break;
+	case LM_DATA_INDICATION:
+		irlmp_data_indication( self, skb); 
+		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
+		break;
+	case LM_UDATA_INDICATION:
+		irlmp_udata_indication( self, skb); 
+		/* irlmp_next_lsap_state( DATA_TRANSFER_READY, info->handle);*/
+		break;
+	case LM_LAP_DISCONNECT_INDICATION:
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+
+		reason = irlmp_convert_lap_reason( self->lap->reason);
+
+		irlmp_disconnect_indication( self, reason, NULL);
+		break;
+	case LM_DISCONNECT_INDICATION:
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+			
+		ASSERT( self->lap != NULL, return;);
+		ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
+	
+		reason = irlmp_convert_lap_reason( self->lap->reason);
+
+		 /* 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_disconnect_indication( self, reason, skb);
+
+		break;
+	default:
+		DEBUG( 4, "irlmp_state_dtr: Unknown event %d\n", event);
+		break;	
+	}	
+}
+
+/*
+ * Function irlmp_state_setup (event, skb, info)
+ *
+ *    SETUP, Station Control has set up the underlying IrLAP connection.
+ *    An LSAP connection request has been transmitted to the peer
+ *    LSAP-Connection Control FSM and we are awaiting reply.
+ */
+static void irlmp_state_setup( struct lsap_cb *self, IRLMP_EVENT event, 
+			       struct sk_buff *skb) 
+{
+	LM_REASON reason;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
+
+	DEBUG( 4, "irlmp_state_setup()\n");
+
+	switch( event) {
+	case LM_CONNECT_CONFIRM:
+		ASSERT( skb != NULL, return;);
+
+		irlmp_next_lsap_state( self, LSAP_DATA_TRANSFER_READY);
+
+		del_timer( &self->watchdog_timer);
+		
+		irlmp_connect_confirm( self, skb);
+		break;
+	case LM_DISCONNECT_INDICATION:
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+
+		del_timer( &self->watchdog_timer);
+
+		ASSERT( self->lap != NULL, return;);
+		ASSERT( self->lap->magic == LMP_LAP_MAGIC, return;);
+		
+		reason = irlmp_convert_lap_reason( self->lap->reason);
+		
+		irlmp_disconnect_indication( self, reason, skb);
+		break;
+	default:
+		DEBUG( 4, "irlmp_state_setup: Unknown event %d\n", event);
+		break;	
+	}
+}
+
+/*
+ * Function irlmp_state_setup_pend (event, skb, info)
+ *
+ *    SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
+ *    user to set up an LSAP connection. A request has been sent to the
+ *    LAP FSM to set up the underlying IrLAP connection, and we
+ *    are awaiting confirm.
+ */
+static void irlmp_state_setup_pend( struct lsap_cb *self, IRLMP_EVENT event, 
+				    struct sk_buff *skb) 
+{
+
+	DEBUG( 4, __FUNCTION__ "()\n"); 
+
+	ASSERT( self != NULL, return;);
+	ASSERT( irlmp != NULL, return;);
+
+	switch( event) {
+	case LM_LAP_CONNECT_CONFIRM:
+		irlmp_send_lcf_pdu( self->lap, self->dlsap_sel, 
+				    self->slsap_sel, CONNECT_CMD, 
+				    self->tmp_skb);
+		irlmp_next_lsap_state( self, LSAP_SETUP);
+		break;
+	case LM_DISCONNECT_INDICATION:
+		del_timer( &self->watchdog_timer);
+
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		break;
+	case LM_WATCHDOG_TIMEOUT:
+		DEBUG( 0, "irlmp_state_setup_pend() WATCHDOG_TIMEOUT!\n");
+
+		/* FIXME: should we do a disconnect_indication? */
+		return;
+		ASSERT( self->lap != NULL, return;);
+		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
+		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
+		break;
+	default:
+		DEBUG( 4, "irlmp_state_setup_pend: Unknown event %d\n", event);
+		break;	
+	}
+}
+
+void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state) 
+{
+	DEBUG( 4, "LMP LAP = %s\n", irlmp_state[state]);
+	self->lap_state = state;
+}
+
+void irlmp_next_lsap_state( struct lsap_cb *self, LSAP_STATE state) 
+{
+	ASSERT( self != NULL, return;);
+
+	DEBUG( 4, "LMP LSAP = %s\n", irlsap_state[state]);
+	self->lsap_state = state;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.1.131/linux/net/irda/irlmp_frame.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlmp_frame.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,373 @@
+/*********************************************************************
+ *                
+ * Filename:      irlmp_frame.c
+ * Version:       0.1
+ * Description:   IrLMP frame implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Tue Aug 19 02:09:59 1997
+ * Modified at:   Wed Dec  9 01:25:47 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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/config.h>
+#include <linux/skbuff.h>
+#include <linux/kernel.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irlmp_frame.h>
+
+static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap, 
+					__u8 slsap, int status);
+
+inline void irlmp_send_data_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap,
+				 int expedited, struct sk_buff *skb)
+{
+	__u8 *frame;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+
+	frame = skb->data;
+
+	frame[0] = dlsap;
+	frame[1] = slsap;
+
+	if ( expedited) {
+		DEBUG( 4, __FUNCTION__ "(), sending expedited data\n");
+		irlap_data_request( self->irlap, skb, FALSE);
+	} else {
+		DEBUG( 4, __FUNCTION__ "(), sending reliable data\n");
+		irlap_data_request( self->irlap, skb, TRUE);	
+	}
+}
+
+/*
+ * Function irlmp_send_lcf_pdu (dlsap, slsap, opcode,skb)
+ *
+ *    Send Link Control Frame to IrLAP
+ */
+void irlmp_send_lcf_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap,
+			 __u8 opcode, struct sk_buff *skb) 
+{
+	__u8 *frame;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	
+	frame = skb->data;
+	
+	frame[0] = dlsap | CONTROL_BIT;
+	frame[1] = slsap;
+
+	frame[2] = opcode;
+
+	if (opcode == DISCONNECT)
+		frame[3] = 0x01; /* Service user request */
+	else
+		frame[3] = 0x00; /* rsvd */
+
+	ASSERT( self->irlap != NULL, return;);
+	irlap_data_request( self->irlap, skb, TRUE);
+}
+
+/*
+ * Function irlmp_input (skb)
+ *
+ *    Used by IrLAP to pass received data frames to IrLMP layer
+ *
+ */
+void irlmp_link_data_indication( struct lap_cb *self, int reliable, 
+				 struct sk_buff *skb)
+{
+	__u8 *fp;
+	__u8  slsap_sel;   /* Source (this) LSAP address */
+	__u8  dlsap_sel;   /* Destination LSAP address */
+	struct lsap_cb *lsap;
+
+	
+	DEBUG( 4, "irlmp_link_data_indication()\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	ASSERT( skb->len > 2, return;);
+
+	fp = skb->data;
+
+	/*
+	 *  The next statements may be confusing, but we do this so that 
+	 *  destination LSAP of received frame is source LSAP in our view
+	 */
+	slsap_sel = fp[0] & ~CONTROL_BIT; 
+	dlsap_sel = fp[1];
+	
+	DEBUG( 4, "slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, 
+	       dlsap_sel);
+	
+	/*
+	 *  Check if this is an incoming connection, since we must deal with
+	 *  it in a different way than other established connections.
+	 */
+	if (( fp[0] & CONTROL_BIT) && ( fp[2] == CONNECT_CMD)) {
+		DEBUG( 4,"Incoming connection, source LSAP=%d, dest LSAP=%d\n",
+		       slsap_sel, dlsap_sel);
+		lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 
+					CONNECT_CMD);
+	} else
+		lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 0);
+
+	if ( lsap == NULL) {
+		DEBUG( 0, "IrLMP, Sorry, no LSAP for received frame!\n");
+		DEBUG( 0, __FUNCTION__ 
+		       "(), slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, 
+		       dlsap_sel);
+		if ( fp[0] & CONTROL_BIT) {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), received control frame %02x\n", fp[2]);
+		} else {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), received data frame\n");
+		}
+		dev_kfree_skb( skb);
+		return;
+	}
+
+	/* 
+	 *  Check if we received a control frame? 
+	 */
+	if ( fp[0] & CONTROL_BIT) {
+		/* DEBUG( 0, "irlmp_input: Got control frame\n"); */
+		switch( fp[2]) {
+		case CONNECT_CMD:
+			DEBUG( 4, "irlmp_input: CONNECT_CMD\n");
+			lsap->lap = self;
+			irlmp_do_lsap_event( lsap, LM_CONNECT_INDICATION, skb);
+			break;
+		case CONNECT_CNF:
+			irlmp_do_lsap_event( lsap, LM_CONNECT_CONFIRM, skb);
+			break;
+		case DISCONNECT:
+			DEBUG( 4, "irlmp_input: Disconnect indication!\n");
+			irlmp_do_lsap_event( lsap, LM_DISCONNECT_INDICATION, 
+					     skb);
+			break;
+		case ACCESSMODE_CMD:
+			DEBUG( 0, "Access mode cmd not implemented!\n");
+			break;
+		case ACCESSMODE_CNF:
+			DEBUG( 0, "Access mode cnf not implemented!\n");
+			break;
+		default:
+			DEBUG( 0, "irlmp_input: Unknown control frame %02x\n",
+			       fp[2]);
+			break;
+		}
+	} else if ( reliable == LAP_RELIABLE) {
+		/* Must be pure data */
+		irlmp_do_lsap_event( lsap, LM_DATA_INDICATION, skb);
+	} else if ( reliable == LAP_UNRELIABLE) {
+		irlmp_do_lsap_event( lsap, LM_UDATA_INDICATION, skb);
+	}
+}
+
+/*
+ * Function irlmp_link_disconnect_indication (reason, userdata)
+ *
+ *    IrLAP has disconnected 
+ *
+ */
+void irlmp_link_disconnect_indication( struct lap_cb *lap, 
+				       struct irlap_cb *irlap, 
+				       LAP_REASON reason, 
+				       struct sk_buff *userdata)
+{
+	DEBUG( 4, "irlmp_link_disconnect_indication()\n");
+
+	ASSERT( lap != NULL, return;);
+	ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
+
+	lap->reason = reason;
+
+        /* FIXME: must do something with the userdata if any */
+
+	/*
+	 *  Inform station state machine
+	 */
+	irlmp_do_lap_event( lap, LM_LAP_DISCONNECT_INDICATION, NULL);
+}
+
+/*
+ * Function irlmp_link_connect_indication (qos)
+ *
+ *    Incoming LAP connection!
+ *
+ */
+void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos,
+				    struct sk_buff *skb) 
+{
+	DEBUG( 4, "irlmp_link_connect_indication()\n");
+
+	/* Copy QoS settings for this session */
+	self->qos = qos;
+
+	irlmp_do_lap_event( self, LM_LAP_CONNECT_INDICATION, skb);
+}
+
+/*
+ * Function irlmp_link_connect_confirm (qos)
+ *
+ *    LAP connection confirmed!
+ *
+ */
+void irlmp_link_connect_confirm( struct lap_cb *self, struct qos_info *qos, 
+				 struct sk_buff *userdata)
+{
+	DEBUG( 4, "irlmp_link_connect_confirm()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+	ASSERT( qos != NULL, return;);
+
+	/* Copy QoS settings for this session */
+	self->qos = qos;
+
+	irlmp_do_lap_event( self, LM_LAP_CONNECT_CONFIRM, NULL);
+}
+
+/*
+ * Function irlmp_link_discovery_confirm (self, log)
+ *
+ *    Called by IrLAP with a list of discoveries after the discovery
+ *    request has been carried out. A NULL log is received if IrLAP
+ *    was unable to carry out the discovery request
+ *
+ */
+void irlmp_link_discovery_confirm( struct lap_cb *self, hashbin_t *log)
+{
+	DEBUG( 4, "irlmp_link_connect_confirm()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
+
+	if ( self->cachelog)
+		hashbin_delete( self->cachelog, (FREE_FUNC) kfree);
+
+	self->cachelog = log;
+      
+	irlmp_do_lap_event( self, LM_LAP_DISCOVERY_CONFIRM, NULL);
+}
+
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+void irlmp_update_cache( struct lsap_cb *self)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Update cache entry */
+	irlmp->cache.dlsap_sel = self->dlsap_sel;
+	irlmp->cache.slsap_sel = self->slsap_sel;
+	irlmp->cache.lsap = self;
+	irlmp->cache.valid = TRUE;
+}
+#endif
+
+/*
+ * Function irlmp_find_handle (dlsap, slsap)
+ *
+ *    Find handle assosiated with destination and source LSAP
+ *
+ */
+static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap_sel,
+					__u8 slsap_sel, int status) 
+{
+	struct lsap_cb *lsap;
+	hashbin_t *queue;
+	
+	DEBUG( 4, "irlmp_find_lsap: dlsap_sel=0x%02x, slsap_sel=0x%02x\n", 
+	       dlsap_sel, slsap_sel);
+	
+	ASSERT( self != NULL, return NULL;);
+	ASSERT( self->magic == LMP_LAP_MAGIC, return NULL;);
+
+	if ( status)
+		queue = irlmp->unconnected_lsaps;
+	else
+		queue = self->lsaps;
+
+	/* 
+	 *  Optimize for the common case. We assume that the last frame
+	 *  received is in the same connection as the last one, so check in
+	 *  cache first to avoid the linear search
+	 */
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+	ASSERT( irlmp != NULL, return NULL;);
+
+	if (( irlmp->cache.valid) && 
+	    ( irlmp->cache.slsap_sel == slsap_sel) && 
+	    ( irlmp->cache.dlsap_sel == dlsap_sel)) 
+	{
+		DEBUG( 4, __FUNCTION__ "(), Using cached LSAP\n");
+		return ( irlmp->cache.lsap);
+	}	
+#endif
+	lsap = ( struct lsap_cb *) hashbin_get_first( queue);
+	while ( lsap != NULL) {
+		/* 
+		 *  Check if source LSAP (in our view!) match, and if
+		 *  dest LSAP is equal to LM_ANY, which is the case
+		 *  for incomming connections 
+		 */
+		DEBUG( 4, "irlmp_find_lsap: "
+		       "LSAP: lsap->dlsap=%d, lsap->slsap=%d\n", 
+		       lsap->dlsap_sel, lsap->slsap_sel);
+		
+		if (( status == CONNECT_CMD) && 
+		    ( lsap->slsap_sel == slsap_sel) &&      
+		    ( lsap->dlsap_sel == LSAP_ANY)) 
+		{
+			DEBUG( 4,"Incoming connection: Setting dlsap_sel=%d\n",
+			       dlsap_sel);
+			lsap->dlsap_sel = dlsap_sel;
+			
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+			irlmp_update_cache( lsap);
+#endif
+			return lsap;
+		}
+		/*
+		 *  Check if source LSAP and dest LSAP selectors match.
+		 */
+		if (( lsap->slsap_sel == slsap_sel) && 
+		    ( lsap->dlsap_sel == dlsap_sel)) 
+		{
+#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+			irlmp_update_cache( lsap);
+#endif
+			return lsap;
+		}
+		lsap = ( struct lsap_cb *) hashbin_get_next( queue);
+	}
+
+	/* Sorry not found! */
+	return NULL;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.1.131/linux/net/irda/irmod.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irmod.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,397 @@
+/*********************************************************************
+ *                
+ * Filename:      irmod.c
+ * Version:       0.8
+ * Description:   IrDA module code and some other stuff
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Dec 15 13:55:39 1997
+ * Modified at:   Mon Dec 14 20:10:28 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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/config.h>
+#include <linux/module.h> 
+#include <linux/init.h>
+#include <asm/segment.h>
+#include <linux/poll.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+
+struct irda irda; /* One global instance */
+
+extern void irda_proc_register(void);
+extern void irda_proc_unregister(void);
+extern int irda_sysctl_register(void);
+extern void irda_sysctl_unregister(void);
+
+extern void irda_proto_init(struct net_proto *pro);
+extern void irda_proto_cleanup(void);
+
+extern int irda_device_init(void);
+extern int irobex_init(void);
+extern int irlan_init(void);
+extern int irlan_client_init(void);
+extern int irlan_server_init(void);
+extern int ircomm_init(void);
+extern int irvtd_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 struct file_operations irda_fops = {
+	NULL,	       /* seek */
+	irda_read,     /* read */
+	irda_write,    /* write */
+	NULL,	       /* readdir */
+	irda_poll,     /* poll */
+	irda_ioctl,    /* ioctl */
+	NULL,	       /* mmap */
+	irda_open,
+	NULL,
+	irda_close,
+	NULL,
+	NULL,          /* fasync */
+};
+
+__initfunc(int irda_init(void))
+{
+        printk( KERN_INFO "Linux Support for the IrDA (tm) protocols (Dag Brattli)\n");
+
+	irda_device_init();
+	irlap_init();
+ 	irlmp_init();
+	iriap_init();
+ 	irttp_init();
+	
+#ifdef CONFIG_PROC_FS
+	irda_proc_register();
+#endif
+#ifdef CONFIG_SYSCTL
+	irda_sysctl_register();
+#endif
+
+	irda.dev.minor = MISC_DYNAMIC_MINOR;
+	irda.dev.name = "irda";
+	irda.dev.fops = &irda_fops;
+	
+	misc_register( &irda.dev);
+
+	/* 
+	 * Initialize modules that got compiled into the kernel 
+	 */
+#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
+#ifdef CONFIG_IRCOMM
+	ircomm_init();
+	irvtd_init();
+#endif
+
+	return 0;
+}
+
+void irda_cleanup(void)
+{
+	misc_deregister( &irda.dev);
+
+#ifdef CONFIG_SYSCTL
+	irda_sysctl_unregister();
+#endif	
+
+#ifdef CONFIG_PROC_FS
+	irda_proc_unregister();
+#endif
+
+	/* Remove higher layers */
+	irttp_cleanup();
+	iriap_cleanup();
+
+	/* Remove lower layers */
+	irda_device_cleanup();
+	irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */
+
+	/* Remove middle layer */
+	irlmp_cleanup();
+}
+
+/*
+ * Function irda_lock (lock)
+ *
+ *    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;
+        }  
+	return TRUE;
+}
+
+/*
+ * Function irda_unlock (lock)
+ *
+ *    Unlock variable. Returns false if lock is already unlocked
+ *
+ */
+inline int irda_unlock( int *lock) {
+	if ( !test_and_clear_bit( 0, (void *) lock))  {
+		printk("Trying to unlock already unlocked variable!\n");
+		return FALSE;
+        }
+	return TRUE;
+}
+
+/*
+ * Function irda_notify_init (notify)
+ *
+ *    Used for initializing the notify structure
+ *
+ */
+void irda_notify_init( struct notify_t *notify)
+{
+
+	notify->data_indication = NULL;
+	notify->udata_indication = NULL;
+	notify->connect_confirm = NULL;
+	notify->connect_indication = NULL;
+	notify->disconnect_indication = NULL;
+	notify->flow_indication = NULL;
+	notify->instance = NULL;
+	strncpy( notify->name, "Unknown", NOTIFY_MAX_NAME);
+}
+
+/*
+ * Function irda_execute_as_process (self, callback, param)
+ *
+ *    If a layer needs to have a function executed with a process context,
+ *    then it can register the function here, and the function will then 
+ *    be executed as fast as possible.
+ *
+ */
+void irda_execute_as_process( void *self, TODO_CALLBACK callback, __u32 param)
+{
+	struct irda_todo *new;
+	struct irmanager_event event;
+
+	/* Make new todo event */
+	new = (struct irda_todo *) kmalloc( sizeof(struct irda_todo),
+					    GFP_ATOMIC);
+	if ( new == NULL) {
+		return;
+	}
+	memset( new, 0, sizeof( struct irda_todo));
+
+	new->self = self;
+	new->callback = callback;
+	new->param = param;
+	
+	/* Queue todo */
+	enqueue_last( &irda.todo_queue, (QUEUE *) new);
+
+	event.event = EVENT_NEED_PROCESS_CONTEXT;
+
+	/* Notify the user space manager */
+	irmanager_notify( &event);
+}
+
+/*
+ * Function irmanger_notify (event)
+ *
+ *    Send an event to the user space manager
+ *
+ */
+void irmanager_notify( struct irmanager_event *event)
+{
+	struct irda_event *new;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Make new IrDA Event */
+	new = (struct irda_event *) kmalloc( sizeof(struct irda_event),
+					     GFP_ATOMIC);
+	if ( new == NULL) {
+		return;	
+	}
+	memset( new, 0, sizeof( struct irda_event));
+	new->event = *event;
+	
+	/* Queue event */
+	enqueue_last( &irda.event_queue, (QUEUE *) new);
+	
+	/* Wake up irmanager sleeping on read */
+	wake_up_interruptible( &irda.wait_queue);
+}
+
+static int irda_open( struct inode * inode, struct file *file)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function irda_ioctl (inode, filp, cmd, arg)
+ *
+ *    Ioctl, used by irmanager to ...
+ *
+ */
+static int irda_ioctl( struct inode *inode, struct file *filp, 
+		       unsigned int cmd, unsigned long arg)
+{
+	struct irda_todo *todo;
+	int err = 0;
+	int size = _IOC_SIZE(cmd);
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	if ( _IOC_DIR(cmd) & _IOC_READ)
+		err = verify_area( VERIFY_WRITE, (void *) arg, size);
+	else if ( _IOC_DIR(cmd) & _IOC_WRITE)
+		err = verify_area( VERIFY_READ, (void *) arg, size);
+	if ( err)
+		return err;
+	
+	switch( cmd) {
+	case IRMGR_IOCTNPC:
+		/* Got process context! */
+		DEBUG( 4, __FUNCTION__ "(), got process context!\n");
+
+		while (( todo = (struct irda_todo *) dequeue_first( 
+			&irda.todo_queue)) != NULL)
+		{
+			todo->callback( todo->self, todo->param);
+
+			kfree( todo);
+		}
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return 0;
+}
+
+static int irda_close( struct inode *inode, struct file *file)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+static ssize_t irda_read( struct file *file, char *buffer, size_t count, 
+			  loff_t *noidea)
+{
+	struct irda_event *event;
+	unsigned long flags;
+	int len;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* * Go to sleep and wait for event if there is no event to be read! */
+	save_flags( flags);
+	cli();
+	if ( !irda.event_queue)
+		interruptible_sleep_on( &irda.wait_queue);
+	restore_flags(flags);
+	
+	/*
+	 *  Ensure proper reaction to signals, and screen out 
+	 *  blocked signals (page 112. linux device drivers)
+	 */
+	if ( signal_pending( current))
+		return -ERESTARTSYS;
+
+	event = (struct irda_event *) dequeue_first( &irda.event_queue);
+
+	len = sizeof(struct irmanager_event);
+	copy_to_user( buffer, &event->event, len);
+
+	/* Finished with event */
+	kfree( event);
+
+	return len;
+}
+
+static ssize_t irda_write( struct file *file, const char *buffer,
+			   size_t count, loff_t *noidea)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	return 0;
+}
+
+static u_int irda_poll( struct file *file, poll_table *wait)
+{
+	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n");
+
+	return 0;
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("The Linux IrDA protocol subsystem"); 
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize the irda module
+ *
+ */
+int init_module(void) 
+{
+	irda_proto_init(NULL);
+
+	return 0;
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Cleanup the irda module
+ *
+ */
+void cleanup_module(void) 
+{
+	irda_proto_cleanup();
+}
+
+#endif
diff -u --recursive --new-file v2.1.131/linux/net/irda/irobex/Config.in linux/net/irda/irobex/Config.in
--- v2.1.131/linux/net/irda/irobex/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irobex/Config.in	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,3 @@
+
+dep_tristate 'IrOBEX protocol' CONFIG_IROBEX $CONFIG_IRDA
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irobex/Makefile linux/net/irda/irobex/Makefile
--- v2.1.131/linux/net/irda/irobex/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irobex/Makefile	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,19 @@
+#
+# Makefile for the Linux IrDA IrOBEX protocol layer.
+#
+# Note! Dependencies are done automagically by 'make dep', which also
+# removes any old dependencies. DON'T put your own dependencies here
+# unless it's something special (ie not a .c file).
+#
+# Note 2! The CFLAGS definition is now in the main makefile...
+
+#O_TARGET :=
+O_OBJS	 := irobex.o
+M_OBJS   := irobex.o
+
+OX_OBJS  += 
+
+include $(TOPDIR)/Rules.make
+
+tar:
+		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.1.131/linux/net/irda/irobex/irobex.c linux/net/irda/irobex/irobex.c
--- v2.1.131/linux/net/irda/irobex/irobex.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irobex/irobex.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1110 @@
+/*********************************************************************
+ *                
+ * Filename:      irobex.c
+ * Version:       0.1
+ * 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:   Mon Dec 14 11:56:26 1998
+ * 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/config.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/ioctl.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <linux/poll.h>
+
+#include <net/irda/irttp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/iriap.h>
+
+#include <net/irda/irobex.h>
+
+/*
+ *  Master structure, only one instance for now!!
+ */
+struct irobex_cb *irobex;
+
+static int irobex_dev_open( struct inode * inode, struct file *file);
+static int irobex_ioctl( struct inode *inode, struct file *filp, 
+			 unsigned int cmd, unsigned long arg);
+
+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);
+static ssize_t irobex_write( struct file *file, const char *buffer,
+			     size_t count, loff_t *noidea);
+static loff_t irobex_seek( struct file *, loff_t, int);
+static u_int irobex_poll( struct file *file, poll_table *wait);
+static int irobex_fasync( int, struct file *, int);
+
+static struct file_operations irobex_fops = {
+	irobex_seek,	/* seek */
+	irobex_read,
+	irobex_write,
+	NULL,		/* readdir */
+	irobex_poll,    /* poll */
+	irobex_ioctl,	/* ioctl */
+	NULL,		/* mmap */
+	irobex_dev_open,
+	NULL,
+	irobex_dev_close,
+	NULL,
+	irobex_fasync,
+};
+
+#ifdef CONFIG_PROC_FS
+static int irobex_proc_read( char *buf, char **start, off_t offset, 
+			     int len, int unused);
+
+extern struct proc_dir_entry proc_irda;
+
+struct proc_dir_entry proc_irobex = {
+	0, 6, "irobex",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL,
+	&irobex_proc_read,
+};
+#endif
+
+/*
+ * Function irobex_init (dev)
+ *
+ *   Initializes the irobex control structure, and registers as a misc
+ *   device
+ *
+ */
+__initfunc(int irobex_init(void))
+{
+	struct irobex_cb *self;
+
+	DEBUG( 4, "--> " __FUNCTION__ "()\n");	
+
+	self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);
+	if ( self == NULL)
+		return -ENOMEM;
+	
+	memset( self, 0, sizeof(struct irobex_cb));
+ 	sprintf( self->devname, "irobex%d", 1); /* Just one instance for now */
+	
+	self->magic = IROBEX_MAGIC;
+	self->rx_flow = self->tx_flow = FLOW_START;
+	
+	self->dev.minor = MISC_DYNAMIC_MINOR;
+	self->dev.name = "irobex";
+	self->dev.fops = &irobex_fops;
+	
+	skb_queue_head_init( &self->rx_queue);
+	init_timer( &self->watchdog_timer);
+
+	irobex = self;
+	
+	misc_register( &self->dev);
+	
+	irobex_register_server( self);
+
+#ifdef CONFIG_PROC_FS
+	proc_register( &proc_irda, &proc_irobex);
+#endif /* CONFIG_PROC_FS */
+		
+	irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, 
+			      irobex_discovery_indication);
+	
+	DEBUG( 4, "irobex_init -->\n");
+	
+	return 0;
+}
+
+/*
+ * Function irobex_cleanup (void)
+ *
+ *     Removes the IrOBEX layer
+ *
+ */
+void irobex_cleanup(void)
+{
+	struct sk_buff *skb;
+	struct irobex_cb *self;
+	
+	DEBUG( 4, "-->" __FUNCTION__ "()\n");
+
+	self = irobex;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);	
+
+	/*
+	 *  Deregister client and server
+	 */
+	irlmp_unregister_layer( S_OBEX, CLIENT | SERVER);
+
+	if ( self->tsap) {
+		irttp_close_tsap( self->tsap);
+		self->tsap = NULL;
+	}
+
+	/* Stop timers */
+	del_timer( &self->watchdog_timer);
+
+	/*
+	 *  Deallocate buffers
+	 */
+	while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
+		dev_kfree_skb( skb);
+	}
+
+#ifdef CONFIG_PROC_FS
+	proc_unregister( &proc_irda, proc_irobex.low_ino);
+#endif
+	
+	misc_deregister( &self->dev);
+	
+	kfree( self);
+	
+	DEBUG( 4, __FUNCTION__ "() -->\n");
+}
+
+/*
+ * Function irobex_read (inode, file, buffer, count)
+ *
+ *    User process wants to read some data
+ *
+ */
+static ssize_t irobex_read( struct file *file, char *buffer, size_t count, 
+			    loff_t *noidea)
+{
+	int len=0;
+	struct irobex_cb *self;
+	struct sk_buff *skb = NULL;
+	int ret;
+	
+	self = irobex;
+
+	ASSERT( self != NULL, return -EIO;);
+	ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
+  
+	DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, conn.=%d, eof=%d\n", 
+	       count, skb_queue_len( &self->rx_queue), self->connected, 
+	       self->eof);
+	
+	/*
+	 *  Check if there is no data to return
+	 */
+	if ( skb_queue_len( &self->rx_queue) == 0) {
+
+		/*
+		 *  Disconnected yet?
+		 */
+		if ( !self->connected) {
+			switch ( self->eof) {
+			case LM_USER_REQUEST:
+				self->eof = FALSE;
+				DEBUG(3, "read_irobex: returning 0\n");
+				ret = 0;
+				break;
+			case LM_LAP_DISCONNECT:
+				self->eof = FALSE;
+				ret = -EIO;
+				break;
+			case LM_LAP_RESET:
+				self->eof = FALSE;
+				ret = -ECONNRESET;
+				break;
+			default:
+				self->eof = FALSE;
+				ret = -EIO;
+				break;
+			}
+			return ret;
+		}
+
+		/* Return if user does not want to block */
+		if ( file->f_flags & O_NONBLOCK)
+			return -EAGAIN;
+
+		/* * Go to sleep and wait for data!  */
+		interruptible_sleep_on( &self->read_wait);
+
+		/*
+		 *  Ensure proper reaction to signals, and screen out 
+		 *  blocked signals (page 112. linux device drivers)
+		 */
+		if ( signal_pending( current))
+			return -ERESTARTSYS;
+	}
+	
+	while ( count && skb_queue_len( &self->rx_queue)) {
+
+		skb = skb_dequeue( &self->rx_queue);
+		
+		/*
+		 *  Check if we have previously stopped IrTTP and we know
+		 *  have more free space in our rx_queue. If so tell IrTTP
+		 *  to start delivering frames again before our rx_queue gets
+		 *  empty
+		 */
+		if ( self->rx_flow == FLOW_STOP) {
+			if ( skb_queue_len( &self->rx_queue) < LOW_THRESHOLD) {
+				DEBUG( 0, __FUNCTION__ "(), Starting IrTTP\n");
+				self->rx_flow = FLOW_START;
+				irttp_flow_request( self->tsap, FLOW_START);
+			}
+		}
+
+		/*  
+		 *  Is the request from the user less that the amount in the 
+		 *  current packet?  
+		 */
+		if ( count <  skb->len) {
+			copy_to_user( buffer+len, skb->data, count);
+			len += count;
+
+			/*
+			 *  Remove copied data from skb and queue
+			 *  it for next read
+			 */
+			skb_pull( skb, count);
+			skb_queue_head( &self->rx_queue, skb);
+			
+			return len;
+		} else {
+			copy_to_user( buffer+len, skb->data, skb->len);
+			count -= skb->len;
+			len += skb->len;
+			
+			dev_kfree_skb( skb);
+		}
+	}
+	return len;
+}
+
+/*
+ * Function irobex_write (inode, file, buffer, count)
+ *
+ *    User process wants to write to device
+ *
+ */
+static ssize_t irobex_write( struct file *file, const char *buffer, 
+			     size_t count, loff_t *noidea)
+{
+	struct irobex_cb *self;
+	struct sk_buff *skb;
+	int data_len = 0;
+	int len = 0;
+	
+	self = irobex;
+	
+	ASSERT( self != NULL, return -EIO;);
+	ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
+
+	DEBUG( 4, __FUNCTION__ ": count = %d\n", count);
+	
+	/*
+	 *  If we are not connected then we just give up!
+	 */
+	if ( !self->connected) {
+		DEBUG( 0, __FUNCTION__ "(): Not connected!\n");
+
+		return -ENOLINK;
+	} 
+
+	/* Check if IrTTP is wants us to slow down */
+	if ( self->tx_flow == FLOW_STOP) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), IrTTP wants us to slow down, going to sleep\n");
+		interruptible_sleep_on( &self->write_wait);
+	}
+	
+	/* Send data to TTP layer possibly as muliple packets */
+	while ( count) {
+
+		/*
+		 *  Check if request is larger than what fits inside a TTP
+		 *  frame
+		 */
+		if ( count < (self->irlap_data_size - IROBEX_MAX_HEADER))
+			data_len = count;
+		else 
+		        data_len = self->irlap_data_size - IROBEX_MAX_HEADER;
+
+		DEBUG( 4, __FUNCTION__ "(), data_len=%d, header_len = %d\n", 
+		       data_len, IROBEX_MAX_HEADER);
+
+		skb = dev_alloc_skb( data_len + IROBEX_MAX_HEADER);
+		if ( skb == NULL) {
+			DEBUG( 0, "irobex - couldn't allocate skbuff!\n");
+			return 0;
+		}
+		
+		skb_reserve( skb, IROBEX_MAX_HEADER);
+		skb_put( skb, data_len);
+		
+		copy_from_user( skb->data, buffer+len, data_len);
+		len += data_len;
+		count -= data_len;
+
+		DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int) skb->len);
+		ASSERT( skb->len <= (self->irlap_data_size-IROBEX_MAX_HEADER),
+			return len;);
+		irttp_data_request( self->tsap, skb);
+	}
+	return (len);
+}
+
+/*
+ * Function irobex_poll (file, wait)
+ *
+ *    
+ *
+ */
+static u_int irobex_poll(struct file *file, poll_table *wait)
+{
+	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n");
+
+	/* check out /usr/src/pcmcia/modules/ds.c for an example */
+	return 0;
+}
+
+/*
+ * Function irobex_fasync (inode, filp, mode)
+ *
+ *    Implementation for SIGIO
+ *
+ */
+static int irobex_fasync( int fd, struct file *filp, int on)
+{
+	struct irobex_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	self = irobex;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IROBEX_MAGIC, return -1;);
+
+	return fasync_helper( fd, filp, on, &self->async);
+}
+
+/*
+ * Function irobex_seek (inode, file, buffer, count)
+ *
+ *    Not implemented yet!
+ *
+ */
+static loff_t irobex_seek( struct file *file, loff_t off, int whence)
+{
+	DEBUG( 0, __FUNCTION__ "(), Not implemented yet!\n");
+
+	return -ESPIPE;
+}
+
+/*
+ * Function irobex_ioctl (inode, filp, cmd, arg)
+ *
+ *    Drivers IOCTL handler, used for connecting and disconnecting
+ *    irobex connections
+ *
+ */
+static int irobex_ioctl( struct inode *inode, struct file *filp, 
+			 unsigned int cmd, unsigned long arg)
+{
+	struct irobex_cb *self;
+	int err = 0;
+	int size = _IOC_SIZE(cmd);
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	self = irobex;
+	
+	ASSERT( self != NULL, return -ENOTTY;);
+	ASSERT( self->magic = IROBEX_MAGIC, return -ENOTTY;);
+	
+	if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC) 
+		return -EINVAL;
+	if ( _IOC_NR(cmd) > IROBEX_IOC_MAXNR)
+		return -EINVAL;
+
+	if ( _IOC_DIR(cmd) & _IOC_READ)
+		err = verify_area( VERIFY_WRITE, (void *) arg, size);
+	else if ( _IOC_DIR(cmd) & _IOC_WRITE)
+		err = verify_area( VERIFY_READ, (void *) arg, size);
+	if ( err)
+		return err;
+
+	switch ( cmd) {
+	case IROBEX_IOCSCONNECT:
+		DEBUG( 0, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
+		
+		/* Already connected? */
+		if ( self->connected)
+			return 0;
+		
+		/*
+		 *  Wait until we have discovered a remote IrOBEX device
+		 */
+		if (( self->daddr == 0) || 
+		    (( jiffies - self->time_discovered) > 500)) {
+			
+			if ( self->daddr != 0) {
+				DEBUG( 0, __FUNCTION__ "(), daddr is old!\n");
+				self->daddr = 0;
+			}
+
+			irlmp_discovery_request( 8);
+			DEBUG( 0, __FUNCTION__ 
+			       "(): Sleep until device discovered\n");
+			
+			/* Timeout after 10 secs. */
+			irobex_start_watchdog_timer( self, 1000);
+			/*
+			 *  Wait for discovery to complete
+			 */
+			interruptible_sleep_on( &self->discover_wait);
+			/* del_timer( &self->watchdog_timer); */
+		}
+		
+		/* Give up if we are unable to discover any remote devices */
+		if ( self->daddr == 0) {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unable to discover any devices!\n");
+			return -ENOTTY;
+		}
+		
+		/* Need to find remote destination TSAP selector? */
+		if ( self->dtsap_sel == 0) {
+			
+			DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
+			
+			/* Timeout after 5 secs. */
+			irobex_start_watchdog_timer( self, 500);
+			iriap_getvaluebyclass_request( self->daddr,
+						       "OBEX", 
+						       "IrDA:TinyTP:LsapSel",
+						       irobex_get_value_confirm,
+						       self);
+			
+			DEBUG( 0, __FUNCTION__ "(): Sleep until IAS answer\n");
+			interruptible_sleep_on( &self->ias_wait);
+			/* del_timer( &self->watchdog_timer); */
+		}	
+		
+		if ( self->dtsap_sel == 0) {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unable to query remote LM-IAS!\n");
+			return -ENOTTY;
+		}
+
+
+		/*
+		 *  Try connect
+		 */
+		DEBUG( 0, __FUNCTION__ "(): Connecting ...\n");
+
+		/* 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!
+		 */
+		DEBUG( 0, __FUNCTION__ "(): Waiting for connection!\n");
+		interruptible_sleep_on( &self->connect_wait);
+
+		del_timer( &self->watchdog_timer);
+		
+		if ( !self->connected) {
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unable to connect to remote device!\n");
+			return -ENOTTY;
+		}
+
+		break;
+	case IROBEX_IOCSDISCONNECT:
+		DEBUG( 0, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
+		if ( !self->connected)
+			return 0;
+
+		irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
+
+		/* Reset values for this instance */
+		self->connected = FALSE;
+		self->eof = 0;
+		self->daddr = 0;
+		self->dtsap_sel = 0;
+		self->rx_flow = FLOW_START;
+		self->tx_flow = FLOW_START;
+		
+		wake_up_interruptible( &self->read_wait);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * Function irobex_dev_open (inode, file)
+ *
+ *    
+ *
+ */
+static int irobex_dev_open( struct inode * inode, struct file *file)
+{
+	struct irobex_cb *self;
+	
+	DEBUG( 4, "open_irobex:\n");
+	
+	self = irobex;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IROBEX_MAGIC, return -1;);
+
+	if ( self->count++) {
+		DEBUG( 3, "open_irobex: count not zero; actual = %d\n",
+		       self->count);
+		self->count--;
+		return -EBUSY;
+	}
+	
+	MOD_INC_USE_COUNT;
+	
+	return 0;
+}
+
+static int  irobex_dev_close( struct inode *inode, struct file *file)
+{
+	struct irobex_cb *self;
+	struct sk_buff *skb;
+	
+	DEBUG( 4, "close_irobex()\n");
+
+	self = irobex;
+
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == IROBEX_MAGIC, return -EBADR;);
+
+	/* Deallocate buffers */
+	while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
+		DEBUG( 3, "irobex_close: freeing SKB\n");
+		dev_kfree_skb( skb);
+	}
+
+	/* if ( self->tsap) { */
+/* 		irttp_close_tsap( self->tsap); */
+/* 		self->tsap = NULL; */
+/* 		self->connected = FALSE; */
+/* 	} */
+
+	/* Remove this filp from the asynchronously notified filp's */
+	irobex_fasync( -1, file, 0);
+
+	self->count--;
+	
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function irobex_discovery_inication (daddr)
+ *
+ *    Remote device discovered, try query the remote IAS to see which
+ *    device it is, and which services it has.
+ *
+ */
+void irobex_discovery_indication( DISCOVERY *discovery) 
+{
+ 	struct irobex_cb *self;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	self = irobex;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+
+	self->daddr = discovery->daddr;
+	self->time_discovered = jiffies;
+	
+	wake_up_interruptible( &self->discover_wait);
+}
+
+/*
+ * Function irobex_disconnect_indication (handle, reason, priv)
+ *
+ *    
+ *
+ */
+void irobex_disconnect_indication( void *instance, void *sap, 
+				   LM_REASON reason, struct sk_buff *userdata)
+{
+	struct irobex_cb *self;
+	
+	DEBUG( 0, __FUNCTION__ "(), reason=%d\n", reason);
+
+	self = ( struct irobex_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+
+/* 	save_flags(flags); */
+/* 	cli(); */
+	
+	self->connected = FALSE;
+	self->eof = reason;
+	self->daddr = 0;
+	self->dtsap_sel = 0;
+	self->rx_flow = self->tx_flow = FLOW_START;
+	
+/* 	restore_flags(flags); */
+
+	wake_up_interruptible( &self->read_wait);
+	wake_up_interruptible( &self->connect_wait);
+	wake_up_interruptible( &self->write_wait);
+	
+	DEBUG( 4, "irobex_disconnect_indication: skb_queue_len=%d\n",
+	       skb_queue_len( &irobex->rx_queue));
+	
+	if ( userdata) {
+	        dev_kfree_skb( userdata);
+
+	}	
+}
+
+/*
+ * 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)
+{
+	struct irobex_cb *self;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	self = ( struct irobex_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+	ASSERT( qos != NULL, return;);
+
+	DEBUG( 0, __FUNCTION__ "(), IrLAP data size=%d\n", 
+	       qos->data_size.value);
+
+	self->irlap_data_size = qos->data_size.value;
+	self->connected = TRUE;
+
+	/*
+	 *  Wake up any blocked process wanting to write. Finally this process
+	 *  can start writing since the connection is now open :-)
+	 */
+	wake_up_interruptible( &self->connect_wait);
+
+	if ( userdata) {
+	        dev_kfree_skb( userdata);
+
+	}
+}
+
+/*
+ * Function irobex_connect_response (handle)
+ *
+ *    Accept incomming connection
+ *
+ */
+void irobex_connect_response( struct irobex_cb *self)
+{
+	struct sk_buff *skb;
+/* 	__u8 *frame; */
+
+	DEBUG( 4, "irobex_connect_response()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);	
+
+	self->connected = TRUE;
+
+	skb = dev_alloc_skb( 64);
+	if (skb == NULL) {
+		DEBUG( 0,"irobex_connect_response: "
+		       "Could not allocate an sk_buff of length %d\n",
+		       64);
+		return;
+	}
+
+	/* Reserve space for MUX_CONTROL and LAP header */
+	skb_reserve( skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER);
+
+	irttp_connect_response( self->tsap, SAR_DISABLE, skb);
+}
+
+/*
+ * Function irobex_connect_indication (handle, skb, priv)
+ *
+ *    Connection request from a remote device
+ *
+ */
+void irobex_connect_indication( void *instance, void *sap, 
+				struct qos_info *qos, int max_sdu_size,
+				struct sk_buff *userdata)
+{
+	struct irmanager_event mgr_event;
+	struct irobex_cb *self;
+	
+	DEBUG( 0, "irobex_connect_indication()\n");
+
+	self = ( struct irobex_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);	
+	ASSERT( userdata != NULL, return;);
+
+	self->eof = FALSE;
+
+	DEBUG( 0, "irobex_connect_indication, skb_len = %d\n", 
+	       (int) userdata->len);
+
+	DEBUG( 0, __FUNCTION__ "(), IrLAP data size=%d\n", 
+	       qos->data_size.value);
+
+	ASSERT( qos->data_size.value >= 64, return;);
+
+	self->irlap_data_size = qos->data_size.value;
+
+	irobex_connect_response( self);
+
+	mgr_event.event = EVENT_IROBEX_START;
+	sprintf( mgr_event.devname, "%s", self->devname);
+	irmanager_notify( &mgr_event);
+
+	wake_up_interruptible( &self->read_wait);
+
+	if ( userdata) {
+	        dev_kfree_skb( userdata);
+	}
+}
+
+/*
+ * Function irobex_data_indication (instance, sap, skb)
+ *
+ *    This function gets the data that is received on the data channel
+ *
+ */
+void irobex_data_indication( void *instance, void *sap, struct sk_buff *skb) 
+{
+
+	struct irobex_cb *self;
+	
+	self = ( struct irobex_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+	ASSERT( skb != NULL, return;);
+	
+	DEBUG( 4, __FUNCTION__ "(), len=%d\n", (int) skb->len);
+	
+	skb_queue_tail( &self->rx_queue, skb);
+	
+	/*
+	 *  Check if queues are beginning to get filled, and inform 
+	 *  IrTTP to slow down if that is the case
+	 */
+	if ( skb_queue_len( &self->rx_queue) > HIGH_THRESHOLD) {
+		DEBUG( 0, __FUNCTION__ 
+		       "(), rx_queue is full, telling IrTTP to slow down\n");
+		self->rx_flow = FLOW_STOP;
+		irttp_flow_request( self->tsap, FLOW_STOP);
+	}
+
+	/*
+	 *  Wake up process blocked on read or select
+	 */
+	wake_up_interruptible( &self->read_wait);
+
+	/* Send signal to asynchronous readers */
+	if ( self->async)
+		kill_fasync( self->async, SIGIO);
+}
+
+/*
+ * Function irobex_flow_indication (instance, sap, cmd)
+ *
+ *    
+ *
+ */
+void irobex_flow_indication( void *instance, void *sap, LOCAL_FLOW flow) 
+{
+	struct irobex_cb *self;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+	
+	self = ( struct irobex_cb *) instance;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+	
+	switch ( flow) {
+	case FLOW_STOP:
+		DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n");
+		self->tx_flow = flow;
+		break;
+	case FLOW_START:
+		self->tx_flow = flow;
+		DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to start again\n");
+		wake_up_interruptible( &self->discover_wait);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+	}
+}
+
+/*
+ * Function irobex_get_value_confirm (obj_id, value)
+ *
+ *    Got results from previous GetValueByClass request
+ *
+ */
+void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
+			       void *priv)
+{
+	struct irobex_cb *self;
+	
+	DEBUG( 4, "irobex_get_value_confirm()\n");
+
+	ASSERT( priv != NULL, return;);
+	self = ( struct irobex_cb *) priv;
+	
+	if ( !self || self->magic != IROBEX_MAGIC) {
+		DEBUG( 0, "irobex_get_value_confirm: bad magic!\n");
+		return;
+	}
+
+	switch ( value->type) {
+	case IAS_INTEGER:
+		DEBUG( 0, "irobex_get_value_confirm() int=%d\n", 
+		       value->t.integer);
+		
+		if ( value->t.integer != -1) {
+			self->dtsap_sel = value->t.integer;
+
+			/*
+			 *  Got the remote TSAP, so wake up any processes
+			 *  blocking on write. We don't do the connect 
+			 *  ourselves since we must make sure there is a 
+			 *  process that wants to make a connection, so we
+			 *  just let that process do the connect itself
+			 */
+			wake_up_interruptible( &self->ias_wait);
+		} else 
+			self->dtsap_sel = 0;
+		break;
+	case IAS_STRING:
+		DEBUG( 0, "irlan_get_value_confirm(), got string %s\n", 
+		       value->t.string);
+		break;
+	case IAS_OCT_SEQ:
+		DEBUG( 0, "irobex_get_value_confirm(), "
+		       "OCT_SEQ not implemented\n");
+		break;
+	case IAS_MISSING:
+		DEBUG( 0, "irobex_get_value_confirm(), "
+		       "MISSING not implemented\n");
+		break;
+	default:
+		DEBUG( 0, "irobex_get_value_confirm(), unknown type!\n");
+		break;
+	}
+}
+
+/*
+ * Function irobex_provider_confirm (dlsap)
+ *
+ *    IrOBEX provider is discovered. We can now establish connections
+ *    TODO: This function is currently not used!
+ */
+void irobex_provider_confirm( struct irobex_cb *self, __u8 dlsap) 
+{
+	/* struct irobex_cb *self = irobex; */
+	struct notify_t notify;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+
+	notify.data_indication = irobex_data_indication;
+	notify.connect_confirm = irobex_connect_confirm;
+	notify.connect_indication = irobex_connect_indication;
+	notify.flow_indication = irobex_flow_indication;
+	notify.disconnect_indication = irobex_disconnect_indication;
+	notify.instance = self;
+	
+	/* Create TSAP's */
+	self->tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT,
+				      &notify);
+	
+/* 	DEBUG( 0, "OBEX allocated TSAP%d for data\n", self->handle); */
+	
+	/* irlan_do_event( IAS_PROVIDER_AVAIL, NULL, &frame); */
+}
+
+/*
+ * Function irobex_register_server(void)
+ *
+ *    Register server support so we can accept incomming connections. We
+ *    must register both a TSAP for control and data
+ * 
+ */
+void irobex_register_server( struct irobex_cb *self)
+{
+	struct notify_t notify;
+	struct ias_object *obj;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+
+	irda_notify_init( &notify);
+
+	notify.connect_confirm       = irobex_connect_confirm;
+	notify.connect_indication    = irobex_connect_indication;
+	notify.disconnect_indication = irobex_disconnect_indication;
+	notify.data_indication       = irobex_data_indication;
+	notify.flow_indication       = irobex_flow_indication;
+	notify.instance = self;
+	strcpy( notify.name, "IrOBEX");
+
+	self->tsap = irttp_open_tsap( TSAP_IROBEX, DEFAULT_INITIAL_CREDIT,
+				      &notify);	
+	if ( self->tsap == NULL) {
+		DEBUG( 0, "irobex_register_server(), "
+		       "Unable to allocate TSAP!\n");
+		return;
+	}
+
+	/* 
+	 *  Register with LM-IAS
+	 */
+	obj = irias_new_object( "OBEX", 0x42343);
+	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IROBEX);
+	irias_insert_object( obj);
+
+}
+
+void irobex_watchdog_timer_expired( unsigned long data)
+{
+	struct irobex_cb *self = ( struct irobex_cb *) data;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IROBEX_MAGIC, return;);
+
+	wake_up_interruptible( &self->discover_wait);
+	wake_up_interruptible( &self->ias_wait);
+	wake_up_interruptible( &self->connect_wait);
+
+	/* irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL); */
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irobex_proc_read (buf, start, offset, len, unused)
+ *
+ *    Give some info to the /proc file system
+ */
+static int irobex_proc_read( char *buf, char **start, off_t offset, 
+			     int len, int unused)
+{
+ 	struct irobex_cb *self;
+
+	self = irobex;
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IROBEX_MAGIC, return -1;);
+
+	len = 0;
+	
+	len += sprintf( buf+len, "ifname: %s ",self->devname);
+	len += sprintf( buf+len, "connected: %s ", 
+			self->connected ? "TRUE": "FALSE");
+	len += sprintf( buf+len, "EOF: %s\n", self->eof ? "TRUE": "FALSE");
+	
+	return len;
+}
+
+#endif /* CONFIG_PROC_FS */
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("The Linux IrOBEX module"); 
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize the IrOBEX module, this function is called by the
+ *    modprobe(1) program.
+ */
+int init_module(void) 
+{
+	DEBUG( 4, "--> irobex: init_module\n");
+	
+	irobex_init();
+	
+	DEBUG( 4, "irobex: init_module -->\n");	
+	
+	return 0;
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Remove the IrOBEX module, this function is called by the rmmod(1)
+ *    program
+ */
+void cleanup_module(void) 
+{
+	DEBUG( 4, "--> irobex, cleanup_module\n");
+	/* 
+	 *  No need to check MOD_IN_USE, as sys_delete_module() checks. 
+	 */
+	
+	/* Free some memory */
+	irobex_cleanup();
+	
+	DEBUG( 4, "irobex, cleanup_module -->\n");
+}
+
+#endif /* MODULE */
+
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.1.131/linux/net/irda/irproc.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irproc.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,386 @@
+/*********************************************************************
+ *                
+ * Filename:      irproc.c
+ * Version:       
+ * Description:   Various entries in the /proc file system
+ * Status:        Experimental.
+ * Author:        Thomas Davis, <ratbert@radiks.net>
+ * Created at:    Sat Feb 21 21:33:24 1998
+ * Modified at:   Wed Dec  9 02:26:45 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1998, Thomas Davis, <ratbert@radiks.net>, 
+ *     All Rights Reserved.
+ *      
+ *     This program is free software; you can redistribute it and/or 
+ *     modify it under the terms of the GNU General Public License as 
+ *     published by the Free Software Foundation; either version 2 of 
+ *     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. 
+ *     
+ *     Portions lifted from the linux/fs/procfs/ files.
+ *
+ ********************************************************************/
+
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+
+#include <net/irda/irmod.h>
+#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_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);
+
+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); */
+
+enum irda_directory_inos {
+	PROC_IRDA_LAP = 1,
+	PROC_IRDA_LMP,
+	PROC_IRDA_TTP,
+	PROC_IRDA_LPT,
+	PROC_IRDA_COMM,
+ 	PROC_IRDA_IRDA_DEVICE,
+	PROC_IRDA_IRIAS
+};
+
+static struct file_operations proc_irda_dir_operations = {
+        NULL,                   /* lseek - default */
+        NULL,                   /* read - bad */
+        NULL,                   /* write - bad */
+        proc_irda_readdir,      /* readdir */
+        NULL,                   /* select - default */
+        NULL,                   /* ioctl - default */
+        NULL,                   /* mmap */
+        NULL,                   /* no special open code */
+        NULL,                   /* no special release code */
+        NULL                    /* can't fsync */
+};
+
+/*
+ * proc directories can do almost nothing..
+ */
+struct inode_operations proc_irda_dir_inode_operations = {
+        &proc_irda_dir_operations,   /* default net directory file-ops */
+        NULL,                   /* create */
+	proc_irda_21x_lookup, 
+        NULL,                   /* link */
+        NULL,                   /* unlink */
+        NULL,                   /* symlink */
+        NULL,                   /* mkdir */
+        NULL,                   /* rmdir */
+        NULL,                   /* mknod */
+        NULL,                   /* rename */ 
+        NULL,                   /* readlink */
+        NULL,                   /* follow_link */
+        NULL,                   /* readpage */
+        NULL,                   /* writepage */
+        NULL,                   /* bmap */
+        NULL,                   /* truncate */   
+        NULL                    /* permission */
+};
+
+struct proc_dir_entry proc_irda = {
+	0, 4, "irda",
+        S_IFDIR | S_IRUGO | S_IXUGO, 2, 0, 0,
+        0, &proc_irda_dir_inode_operations,
+        NULL, NULL,
+        NULL,
+        NULL, NULL
+};
+
+#if 0 
+struct proc_dir_entry proc_lpt = {
+	0, 3, "lpt",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irlpt_proc_read /* get_info */,
+};
+#endif
+
+struct proc_dir_entry proc_discovery = {
+	0, 9, "discovery",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&proc_discovery_read /* get_info */,
+};
+
+struct proc_dir_entry proc_irda_device = {
+	0, 11, "irda_device",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL,
+	&irda_device_proc_read,
+};
+
+struct proc_dir_entry proc_ttp = {
+	0, 5, "irttp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irttp_proc_read /* get_info */,
+};
+
+struct proc_dir_entry proc_lmp = {
+	0, 5, "irlmp",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irlmp_proc_read /* get_info */,
+};
+
+struct proc_dir_entry proc_lap = {
+	0, 5, "irlap",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irlap_proc_read /* get_info */,
+};
+
+struct proc_dir_entry proc_ias = {
+	0, 5, "irias",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irias_proc_read /* get_info */,
+};
+
+/*
+ * Function proc_delete_dentry (dentry)
+ *
+ *    Copy of proc/root.c because this function is invisible to the irda
+ *    module
+ * 
+ */
+static void proc_delete_dentry(struct dentry * dentry)
+{
+	d_drop(dentry);
+}
+
+static struct dentry_operations proc_dentry_operations =
+{
+	NULL,			/* revalidate */
+	NULL,			/* d_hash */
+	NULL,			/* d_compare */
+	proc_delete_dentry	/* d_delete(struct dentry *) */
+};
+
+/*
+ * Function irda_proc_register (void)
+ *
+ *    Register irda entry in /proc file system
+ *
+ */
+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);
+}
+
+/*
+ * Function irda_proc_unregister (void)
+ *
+ *    Unregister irda entry in /proc file system
+ *
+ */
+void irda_proc_unregister(void) {
+	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);
+}
+
+/*
+ * Function proc_irda_21x_lookup (dir, dentry)
+ *
+ *    This is a copy of proc_lookup from the linux-2.1.x 
+ *
+ */
+int proc_irda_21x_lookup(struct inode * dir, struct dentry *dentry)
+{
+	struct inode *inode;
+	struct proc_dir_entry * de;
+	int error;
+
+	error = -ENOTDIR;
+	if (!dir || !S_ISDIR(dir->i_mode))
+		goto out;
+
+	error = -ENOENT;
+	inode = NULL;
+	de = (struct proc_dir_entry *) dir->u.generic_ip;
+	if (de) {
+		for (de = de->subdir; de ; de = de->next) {
+			if (!de || !de->low_ino)
+				continue;
+			if (de->namelen != dentry->d_name.len)
+				continue;
+			if (!memcmp(dentry->d_name.name, de->name, de->namelen)) {
+				int ino = de->low_ino | (dir->i_ino & ~(0xffff));
+				error = -EINVAL;
+				inode = proc_get_inode(dir->i_sb, ino, de);
+				break;
+			}
+		}
+	}
+
+	if (inode) {
+		dentry->d_op = &proc_dentry_operations;
+		d_add(dentry, inode);
+		error = 0;
+	}
+out:
+	return error;
+}
+
+/*
+ * Function proc_irda_readdir (filp, dirent, filldir)
+ *
+ *    This is a copy from linux/fs/proc because the function is invisible
+ *    to the irda module
+ * 
+ */
+static int proc_irda_readdir( struct file *filp, void *dirent, 
+			      filldir_t filldir)
+{
+	struct proc_dir_entry * de;
+	unsigned int ino;
+	int i;
+	
+	struct inode *inode = filp->f_dentry->d_inode;
+	if (!inode || !S_ISDIR(inode->i_mode))
+		return -ENOTDIR;
+	ino = inode->i_ino;
+	de = (struct proc_dir_entry *) inode->u.generic_ip;
+	if (!de)
+		return -EINVAL;
+	i = filp->f_pos;
+	switch (i) {
+	case 0:
+		if (filldir(dirent, ".", 1, i, ino) < 0)
+			return 0;
+		i++;
+		filp->f_pos++;
+		/* fall through */
+	case 1:
+		if (filldir(dirent, "..", 2, i, de->parent->low_ino) < 0)
+			return 0;
+		i++;
+		filp->f_pos++;
+		/* fall through */
+	default:
+		ino &= ~0xffff;
+		de = de->subdir;
+		i -= 2;
+		for (;;) {
+			if (!de)
+				return 1;
+			if (!i)
+				break;
+			de = de->next;
+			i--;
+		}
+		
+		do {
+			if (filldir(dirent, de->name, de->namelen, filp->f_pos,
+				    ino | de->low_ino) < 0)
+				return 0;
+			filp->f_pos++;
+			de = de->next;
+		} while (de);
+	}
+	return 1;
+}
+
+/*
+ * Function proc_discovery_read (buf, start, offset, len, unused)
+ *
+ *    Print discovery information in /proc file system
+ *
+ */
+int proc_discovery_read( char *buf, char **start, off_t offset, int len, 
+			 int unused)
+{
+	DISCOVERY *discovery;
+	struct lap_cb *lap;
+	unsigned long flags;
+
+	if ( !irlmp)
+		return len;
+
+	len = sprintf(buf, "IrLMP: Discovery log:\n\n");	
+
+
+	save_flags(flags);
+	cli();
+
+	lap = ( struct lap_cb *) hashbin_get_first( irlmp->links);
+	while( lap != NULL) {
+		ASSERT( lap->magic == LMP_LAP_MAGIC, return 0;);
+		
+		len += sprintf( buf+len, "Link saddr=0x%08x\n", lap->saddr);
+		discovery = ( DISCOVERY *) hashbin_get_first( lap->cachelog);
+		while ( discovery != NULL) {
+			len += sprintf( buf+len, "  name: %s,", 
+					discovery->info);
+			
+			len += sprintf( buf+len, " hint: ");
+			if ( discovery->hint[0] & HINT_PNP)
+				len += sprintf( buf+len, "PnP Compatible ");
+			if ( discovery->hint[0] & HINT_PDA)
+				len += sprintf( buf+len, "PDA/Palmtop ");
+			if ( discovery->hint[0] & HINT_COMPUTER)
+				len += sprintf( buf+len, "Computer ");
+			if ( discovery->hint[0] & HINT_PRINTER)
+				len += sprintf( buf+len, "Printer ");
+			if ( discovery->hint[0] & HINT_MODEM)
+				len += sprintf( buf+len, "Modem ");
+			if ( discovery->hint[0] & HINT_FAX)
+				len += sprintf( buf+len, "Fax ");
+			if ( discovery->hint[0] & HINT_LAN)
+				len += sprintf( buf+len, "LAN Access");
+			
+			if ( discovery->hint[1] & HINT_TELEPHONY)
+				len += sprintf( buf+len, "Telephony ");
+			if ( discovery->hint[1] & HINT_FILE_SERVER)
+				len += sprintf( buf+len, "File Server ");       
+			if ( discovery->hint[1] & HINT_COMM)
+				len += sprintf( buf+len, "IrCOMM ");
+			if ( discovery->hint[1] & HINT_OBEX)
+				len += sprintf( buf+len, "IrOBEX ");
+			
+			len += sprintf( buf+len, ", daddr: 0x%08x\n", 
+					discovery->daddr);
+			
+			len += sprintf( buf+len, "\n");
+			
+			discovery = ( DISCOVERY *) hashbin_get_next( lap->cachelog);
+		}
+		lap = ( struct lap_cb *) hashbin_get_next( irlmp->links);
+	}
+	restore_flags(flags);
+
+	return len;
+}
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.1.131/linux/net/irda/irqueue.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irqueue.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,770 @@
+/*********************************************************************
+ *                
+ * Filename:      irqueue.c
+ * Version:       0.3
+ * Description:   General queue implementation
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Tue Jun  9 13:29:31 1998
+ * Modified at:   Mon Dec 14 20:11:07 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (C) 1998, Aage Kvalnes <aage@cs.uit.no>
+ *     Copyright (C) 1998, Dag Brattli, 
+ *     All Rights Reserved.
+ *
+ *     This code is taken from the Vortex Operating System written by Aage
+ *     Kvalnes. Aage has agreed that this code can use the GPL licence,
+ *     although he does not use that licence in his own code.
+ *     
+ *     This copyright does however _not_ include the ELF hash() function
+ *     which I currently don't know which licence or copyright it
+ *     has. Please inform me if you know.
+ *      
+ *     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/irqueue.h>
+#include <net/irda/irmod.h>
+
+static QUEUE *dequeue_general( QUEUE **queue, QUEUE* element);
+static __u32 hash( char* name);
+
+/*
+ * Function hashbin_create ( type, name )
+ *
+ *    Create hashbin!
+ *
+ */
+hashbin_t *hashbin_new( int type)
+{
+	hashbin_t* hashbin;
+	
+	DEBUG( 4, "hashbin_create()\n");
+	
+	/*
+	 * Allocate new hashbin
+	 */
+	hashbin = kmalloc( sizeof(hashbin_t), GFP_ATOMIC);
+
+	/*
+	 * Initialize structure
+	 */
+	memset( hashbin, 0, sizeof(hashbin_t));
+	hashbin->hb_type = type;
+	hashbin->magic = HB_MAGIC;
+	
+	return hashbin;
+}
+
+/*
+ * Function hashbin_clear (hashbin, free_func)
+ *
+ *    Remove all entries from the hashbin, see also the comments in 
+ *    hashbin_delete() below
+ */
+int hashbin_clear( hashbin_t* hashbin, FREE_FUNC free_func)
+{
+	QUEUE* queue;
+	int i;
+	
+	ASSERT( hashbin != NULL, return -1;);
+	ASSERT( hashbin->magic == HB_MAGIC, return -1;);
+
+	/*
+	 * Free the entries in the hashbin
+	 */
+	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
+		queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i]);
+		while( queue ) {
+			if ( free_func)
+				(*free_func)( queue );
+			queue = dequeue_first( 
+				(QUEUE**) &hashbin->hb_queue[ i]);
+		}
+	}
+	hashbin->hb_size = 0;
+
+	return 0;
+}
+
+
+/*
+ * Function hashbin_delete (hashbin, free_func)
+ *
+ *    Destroy hashbin, the free_func can be a user supplied special routine 
+ *    for deallocating this structure if it's complex. If not the user can 
+ *    just supply kfree, which should take care of the job.
+ */
+int hashbin_delete( hashbin_t* hashbin, FREE_FUNC free_func)
+{
+	int i;
+	QUEUE* queue;
+
+	DEBUG( 4, "hashbin_destroy()\n");
+	
+	/*
+	 *  Free the entries in the hashbin, TODO: use hashbin_clear when
+	 *  it has been shown to work
+	 */
+	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
+		queue = dequeue_first( (QUEUE**) &hashbin->hb_queue[ i ] );
+		while( queue ) {
+			if ( free_func)
+				(*free_func)( queue );
+			queue = dequeue_first( 
+				(QUEUE**) &hashbin->hb_queue[ i ]);
+		}
+	}
+	
+	/*
+	 *  Free the hashbin structure
+	 */
+	hashbin->magic = ~HB_MAGIC;
+	kfree( hashbin );
+
+	return 0;
+}
+
+/*
+ * Function hashbin_lock (hashbin, hashv, name)
+ *
+ *    Lock the hashbin
+ *
+ */
+void hashbin_lock( hashbin_t* hashbin, __u32 hashv, char* name, 
+		   unsigned long flags)
+{
+	int bin;
+	
+	DEBUG( 0, "hashbin_lock\n");
+
+	ASSERT( hashbin != NULL, return;);
+	ASSERT( hashbin->magic == HB_MAGIC, return;);
+
+	/*
+	 * Locate hashbin
+	 */
+	if ( name )
+		hashv = hash( name );
+	bin = GET_HASHBIN( hashv);
+	
+	/* Synchronize */
+	if ( hashbin->hb_type & HB_GLOBAL ) {
+
+		spin_lock_irqsave( &hashbin->hb_mutex[ bin], flags);
+	} else {
+		save_flags( flags);
+		cli();
+	}
+}
+
+/*
+ * Function hashbin_unlock (hashbin, hashv, name)
+ *
+ *    Unlock the hashbin
+ *
+ */
+void hashbin_unlock( hashbin_t* hashbin, __u32 hashv, char* name, 
+		     unsigned long flags)
+{
+	int bin;
+
+	DEBUG( 0, "hashbin_unlock()\n");
+
+	ASSERT( hashbin != NULL, return;);
+	ASSERT( hashbin->magic == HB_MAGIC, return;);
+	
+	/*
+	 * Locate hashbin
+	 */
+	if ( name )
+		hashv = hash( name );
+	bin = GET_HASHBIN( hashv );
+	
+	/* Release lock */
+	if ( hashbin->hb_type & HB_GLOBAL) {
+		spin_unlock_irq( &hashbin->hb_mutex[ bin]);
+	} else if ( hashbin->hb_type & HB_LOCAL) {
+		restore_flags( flags);
+	}
+}
+
+/*
+ * Function hashbin_insert (hashbin, entry, name)
+ *
+ *    Insert an entry into the hashbin
+ *
+ */
+void hashbin_insert( hashbin_t* hashbin, QUEUE* entry, __u32 hashv, 
+		     char* name)
+{
+	unsigned long flags = 0;
+	int bin;
+
+	DEBUG( 4, "hashbin_insert()\n");
+
+	ASSERT( hashbin != NULL, return;);
+	ASSERT( hashbin->magic == HB_MAGIC, return;);
+
+	/*
+	 * Locate hashbin
+	 */
+	if ( name )
+		hashv = hash( name );
+	bin = GET_HASHBIN( hashv );
+
+	/* Synchronize */
+	if ( hashbin->hb_type & HB_GLOBAL ) {
+		spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
+
+	} else if ( hashbin->hb_type & HB_LOCAL ) {
+		save_flags(flags);
+		cli();
+	} /* Default is no-lock  */
+	
+	/*
+	 * Store name and key
+	 */
+	entry->q_hash = hashv;
+	if ( name )
+		strncpy( entry->q_name, name, 32);
+	
+	/*
+	 * Insert new entry first
+	 * TODO: Perhaps allow sorted lists?
+	 *       -> Merge sort if a sorted list should be created
+	 */
+	if ( hashbin->hb_type & HB_SORTED) {
+	} else {
+		enqueue_first( (QUEUE**) &hashbin->hb_queue[ bin ],
+			       entry);
+	}
+	hashbin->hb_size++;
+
+	/* Release lock */
+	if ( hashbin->hb_type & HB_GLOBAL) {
+
+		spin_unlock_irq( &hashbin->hb_mutex[ bin]);
+
+	} else if ( hashbin->hb_type & HB_LOCAL) {
+		restore_flags( flags);
+	}
+}
+
+/*
+ * Function hashbin_find (hashbin, hashv, name)
+ *
+ *    Find item with the given hashv or name
+ *
+ */
+void* hashbin_find( hashbin_t* hashbin, __u32 hashv, char* name )
+{
+	int bin, found = FALSE;
+	unsigned long flags = 0;
+	QUEUE* entry;
+
+	DEBUG( 4, "hashbin_find()\n");
+
+	ASSERT( hashbin != NULL, return NULL;);
+	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+
+	/*
+	 * Locate hashbin
+	 */
+	if ( name )
+		hashv = hash( name );
+	bin = GET_HASHBIN( hashv );
+	
+	/* Synchronize */
+	if ( hashbin->hb_type & HB_GLOBAL ) {
+		spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
+
+	} else if ( hashbin->hb_type & HB_LOCAL ) {
+		save_flags(flags);
+		cli();
+	} /* Default is no-lock  */
+	
+	/*
+	 * Search for entry
+	 */
+	entry = hashbin->hb_queue[ bin];
+	if ( entry ) {
+		do {
+			/*
+			 * Check for key
+			 */
+			if ( entry->q_hash == hashv ) {
+				/*
+				 * Name compare too?
+				 */
+				if ( name ) {
+					if ( strcmp( entry->q_name, name ) == 0 ) {
+						found = TRUE;
+						break;
+					}
+				} else {
+					found = TRUE;
+					break;
+				}
+			}
+			entry = entry->q_next;
+		} while ( entry != hashbin->hb_queue[ bin ] );
+	}
+	
+	/* Release lock */
+	if ( hashbin->hb_type & HB_GLOBAL) {
+		spin_unlock_irq( &hashbin->hb_mutex[ bin]);
+
+	} else if ( hashbin->hb_type & HB_LOCAL) {
+		restore_flags( flags);
+	}
+	
+	if ( found ) 
+		return entry;
+	else
+		return NULL;
+}
+
+void *hashbin_remove_first( hashbin_t *hashbin)
+{
+	unsigned long flags;
+	QUEUE *entry = NULL;
+
+	save_flags(flags);
+	cli();
+
+	entry = hashbin_get_first( hashbin);
+	if ( entry != NULL)
+		hashbin_remove( hashbin, entry->q_hash, NULL);
+
+	restore_flags( flags);
+
+	return entry;
+}
+
+
+/*
+ * Function hashbin_remove (hashbin, name)
+ *
+ *    Remove entry with the given name
+ *
+ */
+void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
+{
+	int   bin, found = FALSE;
+	unsigned long flags = 0;
+	QUEUE* entry;
+
+	DEBUG( 4, "hashbin_remove()\n");
+
+	ASSERT( hashbin != NULL, return NULL;);
+	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+	
+	/*
+	 * Locate hashbin
+	 */
+	if ( name )
+		hashv = hash( name );
+	bin = GET_HASHBIN( hashv );
+
+	if ( hashbin->hb_type & HB_GLOBAL ) {
+		spin_lock_irqsave( &hashbin->hb_mutex[ bin ], flags);
+
+	} else if ( hashbin->hb_type & HB_LOCAL ) {
+		save_flags(flags);
+		cli();
+	} /* Default is no-lock  */
+
+	/*
+	 * Search for entry
+	 */
+	entry = hashbin->hb_queue[ bin ];
+	if ( entry ) {
+		do {
+			/*
+			 * Check for key
+			 */
+			if ( entry->q_hash == hashv ) {
+				/*
+				 * Name compare too?
+				 */
+				if ( name ) {
+					if ( strcmp( entry->q_name, name) == 0)
+					{
+						found = TRUE;
+						break;
+					}
+				} else {
+					found = TRUE;
+					break;
+				}
+			}
+			entry = entry->q_next;
+		} while ( entry != hashbin->hb_queue[ bin ] );
+	}
+	
+	/*
+	 * If entry was found, dequeue it
+	 */
+	if ( found ) {
+		dequeue_general( (QUEUE**) &hashbin->hb_queue[ bin ],
+				 (QUEUE*) entry );
+		hashbin->hb_size--;
+
+		/*
+		 *  Check if this item is the currently selected item, and in
+		 *  that case we must reset hb_current
+		 */
+		if ( entry == hashbin->hb_current)
+			hashbin->hb_current = NULL;
+	}
+
+	/* Release lock */
+	if ( hashbin->hb_type & HB_GLOBAL) {
+		spin_unlock_irq( &hashbin->hb_mutex[ bin]);
+
+	} else if ( hashbin->hb_type & HB_LOCAL) {
+		restore_flags( flags);
+	}
+       
+	
+	/* Return */
+	if ( found ) 
+		return entry;
+	else
+		return NULL;
+	
+}
+
+/*
+ * Function hashbin_get_first (hashbin)
+ *
+ *    Get a pointer to first element in hashbin, this function must be
+ *    called before any calls to hashbin_get_next()!
+ *
+ */
+QUEUE *hashbin_get_first( hashbin_t* hashbin) 
+{
+	QUEUE *entry;
+	int i;
+
+	ASSERT( hashbin != NULL, return NULL;);
+	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+
+	if ( hashbin == NULL)
+		return NULL;
+
+	for ( i = 0; i < HASHBIN_SIZE; i ++ ) {
+		entry = hashbin->hb_queue[ i];
+		if ( entry) {
+			hashbin->hb_current = entry;
+			return entry;
+		}
+	}
+	/*
+	 *  Did not find any item in hashbin
+	 */
+	return NULL;
+}
+
+/*
+ * Function hashbin_get_next (hashbin)
+ *
+ *    Get next item in hashbin. A series of hashbin_get_next() calls must
+ *    be started by a call to hashbin_get_first(). The function returns
+ *    NULL when all items have been traversed
+ * 
+ */
+QUEUE *hashbin_get_next( hashbin_t *hashbin)
+{
+	QUEUE* entry;
+	int bin;
+	int i;
+
+	ASSERT( hashbin != NULL, return NULL;);
+	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
+
+	if ( hashbin->hb_current == NULL) {
+		ASSERT( hashbin->hb_current != NULL, return NULL;);
+		return NULL;
+	}	
+	entry = hashbin->hb_current->q_next;
+	bin = GET_HASHBIN( entry->q_hash);
+
+	/*  
+	 *  Make sure that we are not back at the beginning of the queue
+	 *  again 
+	 */
+	if ( entry != hashbin->hb_queue[ bin ]) {
+		hashbin->hb_current = entry;
+
+		return entry;
+	}
+
+	/*
+	 *  Check that this is not the last queue in hashbin
+	 */
+	if ( bin >= HASHBIN_SIZE)
+		return NULL;
+	
+	/*
+	 *  Move to next queue in hashbin
+	 */
+	bin++;
+	for ( i = bin; i < HASHBIN_SIZE; i++ ) {
+		entry = hashbin->hb_queue[ i];
+		if ( entry) {
+			hashbin->hb_current = entry;
+			
+			return entry;
+		}
+	}
+	return NULL;
+}
+
+/*
+ * Function enqueue_last (queue, proc)
+ *
+ *    Insert item into end of queue.
+ *
+ */
+static void __enqueue_last( QUEUE **queue, QUEUE* element)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/*
+	 * Check if queue is empty.
+	 */
+	if ( *queue == NULL ) {
+		/*
+		 * Queue is empty.  Insert one element into the queue.
+		 */
+		element->q_next = element->q_prev = *queue = element;
+		
+	} else {
+		/*
+		 * Queue is not empty.  Insert element into end of queue.
+		 */
+		element->q_prev         = (*queue)->q_prev;
+		element->q_prev->q_next = element;
+		(*queue)->q_prev        = element;
+		element->q_next         = *queue;
+	}	
+}
+
+inline void enqueue_last( QUEUE **queue, QUEUE* element)
+{
+	unsigned long flags;
+	
+        save_flags(flags);
+        cli();
+
+        __enqueue_last( queue, element);
+
+        restore_flags(flags);
+}
+
+/*
+ * Function enqueue_first (queue, proc)
+ *
+ *    Insert item first in queue.
+ *
+ */
+void enqueue_first(QUEUE **queue, QUEUE* element)
+{
+	
+	DEBUG( 4, "enqueue_first()\n");
+
+	/*
+	 * Check if queue is empty.
+	 */
+	if ( *queue == NULL ) {
+		/*
+		 * Queue is empty.  Insert one element into the queue.
+		 */
+		element->q_next = element->q_prev = *queue = element;
+		
+	} else {
+		/*
+		 * Queue is not empty.  Insert element into front of queue.
+		 */
+		element->q_next          = (*queue);
+		(*queue)->q_prev->q_next = element;
+		element->q_prev          = (*queue)->q_prev;
+		(*queue)->q_prev         = element;
+		(*queue)                 = element;
+	}
+}
+
+/*
+ * Function enqueue_queue (queue, list)
+ *
+ *    Insert a queue (list) into the start of the first queue
+ *
+ */
+void enqueue_queue( QUEUE** queue, QUEUE** list )
+{
+	QUEUE* tmp;
+	
+	/*
+	 * Check if queue is empty
+	 */ 
+	if ( *queue ) {
+		(*list)->q_prev->q_next  = (*queue);
+		(*queue)->q_prev->q_next = (*list); 
+		tmp                      = (*list)->q_prev;
+		(*list)->q_prev          = (*queue)->q_prev;
+		(*queue)->q_prev         = tmp;
+	} else {
+		*queue                   = (*list); 
+	}
+	
+	(*list) = NULL;
+}
+
+/*
+ * Function enqueue_second (queue, proc)
+ *
+ *    Insert item behind head of queue.
+ *
+ */
+#if 0
+static void enqueue_second(QUEUE **queue, QUEUE* element)
+{
+	DEBUG( 0, "enqueue_second()\n");
+
+	/*
+	 * Check if queue is empty.
+	 */
+	if ( *queue == NULL ) {
+		/*
+		 * Queue is empty.  Insert one element into the queue.
+		 */
+		element->q_next = element->q_prev = *queue = element;
+		
+	} else {
+		/*
+		 * Queue is not empty.  Insert element into ..
+		 */
+		element->q_prev = (*queue);
+		(*queue)->q_next->q_prev = element;
+		element->q_next = (*queue)->q_next;
+		(*queue)->q_next = element;
+	}
+}
+#endif
+
+/*
+ * Function dequeue (queue)
+ *
+ *    Remove first entry in queue
+ *
+ */
+QUEUE *dequeue_first(QUEUE **queue)
+{
+	QUEUE *ret;
+
+	DEBUG( 4, "dequeue_first()\n");
+	
+	/*
+	 * Set return value
+	 */
+	ret =  *queue;
+	
+	if ( *queue == NULL ) {
+		/*
+		 * Queue was empty.
+		 */
+	} else if ( (*queue)->q_next == *queue ) {
+		/* 
+		 *  Queue only contained a single element. It will now be
+		 *  empty.  
+		 */
+		*queue = NULL;
+	} else {
+		/*
+		 * Queue contained several element.  Remove the first one.
+		 */
+		(*queue)->q_prev->q_next = (*queue)->q_next;
+		(*queue)->q_next->q_prev = (*queue)->q_prev;
+		*queue = (*queue)->q_next;
+	}
+	
+	/*
+	 * Return the removed entry (or NULL of queue was empty).
+	 */
+	return ret;
+}
+
+/*
+ * Function dequeue_general (queue, element)
+ *
+ *
+ */
+static QUEUE *dequeue_general(QUEUE **queue, QUEUE* element)
+{
+	QUEUE *ret;
+	
+	DEBUG( 4, "dequeue_general()\n");
+	
+	/*
+	 * Set return value
+	 */
+	ret =  *queue;
+		
+	if ( *queue == NULL ) {
+		/*
+		 * Queue was empty.
+		 */
+	} if ( (*queue)->q_next == *queue ) {
+		/* 
+		 *  Queue only contained a single element. It will now be
+		 *  empty.  
+		 */
+		*queue = NULL;
+		
+	} else {
+		/*
+		 *  Remove specific element.
+		 */
+		element->q_prev->q_next = element->q_next;
+		element->q_next->q_prev = element->q_prev;
+		if ( (*queue) == element)
+			(*queue) = element->q_next;
+	}
+	
+	/*
+	 * Return the removed entry (or NULL of queue was empty).
+	 */
+	return ret;
+}
+
+/*
+ * Function hash (name)
+ *
+ *    This function hash the input string 'name' using the ELF hash
+ *    function for strings.
+ */
+static __u32 hash( char* name)
+{
+	__u32 h = 0;
+	__u32 g;
+	
+	while(*name) {
+		h = (h<<4) + *name++;
+		if ((g = (h & 0xf0000000)))
+			h ^=g>>24;
+		h &=~g;
+	}
+	return h;
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.1.131/linux/net/irda/irsysctl.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irsysctl.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,88 @@
+/*********************************************************************
+ *                
+ * Filename:      irsysctl.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Sun May 24 22:12:06 1998
+ * Modified at:   Wed Dec  9 01:29:22 1998
+ * Modified by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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/mm.h>
+#include <linux/ctype.h>
+#include <linux/sysctl.h>
+#include <asm/segment.h>
+
+#define NET_IRDA 412 /* Random number */
+enum { DISCOVERY=1, DEVNAME, COMPRESSION };
+
+extern int sysctl_discovery;
+int sysctl_compression = 0;
+extern char sysctl_devname[];
+
+/* One file */
+static ctl_table irda_table[] = {
+	{ DISCOVERY, "discovery", &sysctl_discovery,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ DEVNAME, "devname", sysctl_devname,
+	  65, 0644, NULL, &proc_dostring, &sysctl_string},
+	{ COMPRESSION, "compression", &sysctl_compression,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
+	{ 0 }
+};
+
+/* One directory */
+static ctl_table irda_net_table[] = {
+	{ NET_IRDA, "irda", NULL, 0, 0555, irda_table },
+	{ 0 }
+};
+
+/* The parent directory */
+static ctl_table irda_root_table[] = {
+	{ CTL_NET, "net", NULL, 0, 0555, irda_net_table },
+	{ 0 }
+};
+
+static struct ctl_table_header *irda_table_header;
+
+/*
+ * Function irda_sysctl_register (void)
+ *
+ *    Register our sysctl interface
+ *
+ */
+int irda_sysctl_register(void)
+{
+	irda_table_header = register_sysctl_table( irda_root_table, 0);
+	if ( !irda_table_header)
+		return -ENOMEM;
+	return 0;
+}
+
+/*
+ * Function irda_sysctl_unregister (void)
+ *
+ *    Unregister our sysctl interface
+ *
+ */
+void irda_sysctl_unregister(void) 
+{
+	unregister_sysctl_table( irda_table_header);
+}
+
+
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.1.131/linux/net/irda/irttp.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irttp.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,1442 @@
+/*********************************************************************
+ *                
+ * Filename:      irttp.c
+ * Version:       0.4
+ * 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:   Mon Dec 14 11:53:19 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/config.h>
+#include <linux/skbuff.h>
+#include <linux/init.h>
+#include <linux/config.h>
+
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+
+struct irttp_cb *irttp = NULL;
+
+static void __irttp_close_tsap( struct tsap_cb *self);
+
+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_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)
+ *
+ *    Initialize the IrTTP layer. Called by module initialization code
+ *
+ */
+__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)
+			return -ENOMEM;
+	}
+	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");
+		return -ENOMEM;
+	}
+	
+	return 0;
+}
+
+/*
+ * Function irttp_cleanup (void)
+ *
+ *    Called by module destruction/cleanup code
+ *
+ */
+void irttp_cleanup(void) 
+{
+	DEBUG( 4, "irttp_cleanup\n");
+	
+	/* Check for main structure */
+	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);
+
+	irttp->magic = ~TTP_MAGIC;
+	
+	/* De-allocate main structure */
+	kfree( irttp);
+
+	irttp = NULL;
+}
+
+/*
+ * 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 notify_t ttp_notify;
+	struct tsap_cb *self;
+	struct lsap_cb *lsap;
+
+	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 "
+			"TSAP control block!\n");
+		return NULL;
+	}
+	memset( self, 0, sizeof(struct tsap_cb));
+
+	init_timer( &self->todo_timer);
+
+	/* Initialize callbacks for IrLMP to use */
+
+	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);
+
+	/*
+	 *  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");
+		return NULL;
+	}
+	
+	/*
+	 *  If user specified LSAP_ANY as source TSAP selector, then IrLMP
+	 *  will replace it with whatever source selector which is free, so
+	 *  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);
+
+	self->notify = *notify;
+	self->lsap = lsap;
+	self->magic = TTP_TSAP_MAGIC;
+
+	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);
+
+	if ( credit > TTP_MAX_QUEUE)
+		self->initial_credit = TTP_MAX_QUEUE;
+	else
+		self->initial_credit = credit;
+	
+	return self;
+}
+
+/*
+ * Function irttp_close (handle)
+ *
+ *    Remove an instance of a TSAP. This function should only deal with the
+ *    deallocation of the TSAP, and resetting of the TSAPs values;
+ *
+ */
+static void __irttp_close_tsap( struct tsap_cb *self)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* First make sure we're connected. */
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+
+	irttp_flush_queues( self);
+
+	del_timer( &self->todo_timer);
+
+	self->connected = FALSE;
+	self->magic = ~TTP_TSAP_MAGIC;
+
+	/*
+	 *  Deallocate structure
+	 */
+	kfree( self);
+
+	DEBUG( 4, "irttp_close_tsap() -->\n");
+}
+
+/*
+ * Function irttp_close (self)
+ *
+ *    Remove TSAP from list of all TSAPs and then deallocate all resources
+ *    associated with this TSAP
+ *
+ */
+void irttp_close_tsap( struct tsap_cb *self)
+{
+	struct tsap_cb *tsap;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+
+	tsap = hashbin_remove( irttp->tsaps, self->stsap_sel, NULL);
+
+	ASSERT( tsap == self, return;);
+
+	/* Close corresponding LSAP */
+	if ( self->lsap) {
+		irlmp_close_lsap( self->lsap);
+		self->lsap = NULL;
+	}
+
+	__irttp_close_tsap( self);
+}
+
+/*
+ * Function irttp_udata_request (self, skb)
+ *
+ *    Send unreliable data on this TSAP
+ *
+ */
+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;);
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Check that nothing bad happens */
+	if (( skb->len == 0) || ( !self->connected)) {
+		DEBUG( 0, __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");
+		return -1;
+	}
+		    
+	irlmp_udata_request( self->lsap, skb);
+	self->stats.tx_packets++;
+
+	return 0;
+}
+
+/*
+ * Function irttp_data_request (handle, skb)
+ *
+ *    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) 
+{
+	__u8 *frame;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
+	ASSERT( skb != NULL, return -1;);
+
+	IS_SKB( skb, return -1;);
+
+	/* Check that nothing bad happens */
+	if (( skb->len == 0) || ( !self->connected)) {
+		DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n");
+		return -1;
+	}
+
+	/*  
+	 *  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__ 
+		       "(), SAR disabled, and data is to large for IrLAP!\n");
+		return -1;
+	}
+
+	/* 
+	 *  Check if SAR is enabled, and the frame is larger than the 
+	 *  TxMaxSduSize 
+	 */
+	if (( self->tx_max_sdu_size != 0) && 
+	    (skb->len > self->tx_max_sdu_size))
+	{
+		DEBUG( 0, __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) {
+		/*
+		 *  Give it a chance to empty itself
+		 */
+		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)) {
+		/* Queue frame */
+		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);
+	} else {
+		/*
+		 *  Fragment the frame, this function will also queue the
+		 *  fragments, we don't care about the fact the the transmit
+		 *  queue may be overfilled by all the segments for a little
+		 *  while
+		 */
+		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)) {
+		
+		/* 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);
+		}
+ 	}
+	
+	/* Try to make some progress */
+	irttp_run_tx_queue( self);
+	
+	return 0;
+}
+
+/*
+ * Function irttp_xmit (self)
+ *
+ *    If possible, transmit a frame queued for transmission.
+ *
+ */
+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)
+		return;
+
+	while (( self->send_credit > 0) && !skb_queue_empty( &self->tx_queue)){
+
+		skb = skb_dequeue( &self->tx_queue);
+		ASSERT( skb != NULL, return;);
+		
+		/* Make room for TTP header */
+		ASSERT( skb_headroom( skb) >= TTP_HEADER, return;);
+				
+		/*
+		 *  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); 
+		cli();
+
+		n = self->avail_credit;
+		self->avail_credit = 0;
+		
+		/* Only space for 127 credits in frame */
+		if ( n > 127) {
+			self->avail_credit = n-127;
+			n = 127;
+		}
+		self->remote_credit += n;
+		self->send_credit--;
+
+		restore_flags(flags);
+
+		DEBUG( 4, "irttp_xmit: Giving away %d credits\n", n);
+		
+		/* 
+		 *  More bit must be set by the data_request() or fragment() 
+		 *  functions
+		 */
+		frame = skb->data;
+
+		DEBUG( 4, __FUNCTION__ "(), More=%s\n", frame[0] & 0x80 ? 
+		       "TRUE" : "FALSE" );
+
+		frame[0] |= (__u8) (n & 0x7f);
+		
+		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)) { 
+			self->tx_sdu_busy = FALSE;
+			
+			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);
+	}
+}
+
+/*
+ * Function irttp_give_credit (self)
+ *
+ *    Send a dataless flowdata TTP-PDU and give available credit to peer
+ *    TSAP
+ */
+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;);	
+
+	DEBUG( 4, "irttp_give_credit() 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);
+		return;
+	}
+
+	/* Reserve space for LMP, and 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);
+	cli();
+
+	n = self->avail_credit;
+	self->avail_credit = 0;
+	
+	/* Only space for 127 credits in frame */
+	if ( n > 127) {
+		self->avail_credit = n - 127;
+		n = 127;
+	}
+	self->remote_credit += n;
+
+	restore_flags(flags);
+
+	skb_put( tx_skb, 1);
+	tx_skb->data[0] = (__u8) ( n & 0x7f);
+	
+	irlmp_data_request( self->lsap, tx_skb);
+	self->stats.tx_packets++;
+}
+
+/*
+ * Function irttp_udata_indication (instance, sap, skb)
+ *
+ *    
+ *
+ */
+void irttp_udata_indication( void *instance, void *sap, struct sk_buff *skb) 
+{
+	struct tsap_cb *self;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	self = (struct tsap_cb *) instance;
+
+	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);
+	}
+	self->stats.rx_packets++;
+}
+
+/*
+ * Function irttp_data_indication (handle, skb)
+ *
+ *    Receive segment from IrLMP. 
+ *
+ */
+void irttp_data_indication( void *instance, void *sap, struct sk_buff *skb)
+{
+	struct tsap_cb *self;
+	int more;
+	int n;
+	__u8 *frame;
+	
+	self = (struct tsap_cb *) instance;
+
+	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", 
+	       n, self->stsap_sel);
+
+	self->stats.rx_packets++;
+
+	/* 
+	 *  Data or dataless frame? Dataless frames only contain the 
+	 *  TTP_HEADER
+	 */
+	if ( skb->len == 1) {
+		/* Dataless flowdata TTP-PDU */
+		self->send_credit += n;
+	} else {
+		/* Deal with inbound credit */
+		self->send_credit += n;
+		self->remote_credit--;
+		
+		/* 
+		 *  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);
+	} 
+
+	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)) 
+	{
+		/* Schedule to start immediately after this thread */
+		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);
+}
+
+/*
+ * Function irttp_flow_request (self, command)
+ *
+ *    This funtion could be used by the upper layers to tell IrTTP to stop
+ *    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)
+{
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+
+	switch ( flow) {
+	case FLOW_STOP:
+		DEBUG( 0, __FUNCTION__ "(), flow stop\n");
+		self->rx_sdu_busy = TRUE;
+		break;
+	case FLOW_START:
+		DEBUG( 0, __FUNCTION__ "(), flow start\n");
+		self->rx_sdu_busy = FALSE;
+		
+		irttp_run_rx_queue( self);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
+	}
+}
+	
+/*
+ * Function irttp_connect_request (self, dtsap_sel, daddr, qos)
+ *
+ *    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) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+	__u8 n;
+	
+	DEBUG( 4, __FUNCTION__ "(), max_sdu_size=%d\n", max_sdu_size); 
+	
+	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);
+			return;
+		}
+		
+		/* Reserve space for MUX_CONTROL and 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) >= 
+			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
+	}
+
+	/* Initialize connection parameters */
+	self->connected = FALSE;
+	self->avail_credit = 0;
+	self->rx_max_sdu_size = max_sdu_size;
+	self->rx_sdu_size = 0;
+	self->rx_sdu_busy = FALSE;
+	self->dtsap_sel = dtsap_sel;
+
+	n = self->initial_credit;
+
+	self->remote_credit = 0;
+	self->send_credit = 0;
+	
+	/*
+	 *  Give away max 127 credits for now
+	 */
+	if ( n > 127) {
+		self->avail_credit=n-127;
+		n = 127;
+	}
+
+	self->remote_credit = n;
+
+	/* SAR enabled? */
+	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[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! */
+	} else {
+		/* Insert plain 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);
+}
+
+/*
+ * Function irttp_connect_confirm (handle, qos, skb)
+ *
+ *    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) 
+{
+	struct tsap_cb *self;
+	__u8 *frame;
+	__u8 n;
+	int parameters;
+
+	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;);
+
+	self->max_seg_size = max_seg_size-LMP_HEADER-LAP_HEADER;
+
+	/*
+	 *  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", 
+		       qos->baud_rate.bits);			
+		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);
+	
+	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");
+		
+		self->tx_max_sdu_size = ntohs(*(__u16 *)(frame+4));
+		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);
+
+	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);
+	}
+}
+
+/*
+ * Function irttp_connect_indication (handle, skb)
+ *
+ *    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) 
+{
+	struct tsap_cb *self;
+	__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;);
+
+	/* FIXME: just remove this when we know its working */
+	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);
+
+	/* FIXME: Need to update dtsap_sel if its equal to LSAP_ANY */
+/* 	if ( self->dtsap_sel == LSAP_ANY) */
+/* 		self->dtsap_sel = lsap->dlsap_sel; */
+
+	frame = skb->data;
+	n = frame[0] & 0x7f;
+
+	self->send_credit = n;
+	self->tx_max_sdu_size = 0;
+	
+	parameters = frame[0] & 0x80;	
+	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, "irttp_connect_indication: initial send_credit=%d\n", n);
+
+	skb_pull( skb, 1);
+
+	if ( self->notify.connect_indication) {
+		self->notify.connect_indication( self->notify.instance, self, 
+						 qos, self->rx_max_sdu_size, 
+						 skb);
+	}
+}
+
+/*
+ * Function irttp_connect_response (handle, userdata)
+ *
+ *    Service user is accepting the connection, just pass it down to
+ *    IrLMP!
+ * 
+ */
+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;);
+
+	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);
+			return;
+		}
+
+		/* Reserve space for MUX_CONTROL and 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) >= 
+			(TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER), return;);
+	}
+	
+	self->avail_credit = 0;
+	self->remote_credit = 0;
+	self->rx_max_sdu_size = max_sdu_size;
+	self->rx_sdu_size = 0;
+	self->rx_sdu_busy = FALSE;
+
+	n = self->initial_credit;
+
+	/* Frame has only space for max 127 credits (7 bits) */
+	if ( n > 127) {
+		self->avail_credit = n - 127;
+		n = 127;
+	}
+
+	self->remote_credit = n;
+	self->connected = TRUE;
+
+	/* SAR enabled? */
+	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[0] = TTP_PARAMETERS | n;
+		frame[1] = 0x04; /* Length */
+		frame[2] = 0x01; /* MaxSduSize */
+		frame[3] = 0x02; /* Value length */
+		*((__u16 *) (frame+4))= htons( max_sdu_size);
+	} else {
+		/* Insert TTP header */
+		frame = skb_push( skb, TTP_HEADER);
+		
+		frame[0] = n & 0x7f;
+	}
+	 
+	irlmp_connect_response( self->lsap, skb);
+}
+
+/*
+ * 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)
+{
+	struct sk_buff *skb;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+
+	/* Already disconnected? */
+	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);
+		}
+
+		/* Try to make some progress */
+		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" );
+			
+			/* 
+			 *  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) {
+			/* 
+			 *  Must delay disconnect til after all data segments
+			 *  have been sent an the tx_queue is empty
+			 */
+			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
+			 */
+			return;
+		}
+	}
+	DEBUG( 0, __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);
+			return;
+		}
+
+		/* 
+		 *  Reserve space for MUX and LAP header 
+		 */
+		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+
+		userdata = skb;
+	}
+	irlmp_disconnect_request( self->lsap, userdata);
+}
+
+/*
+ * Function irttp_disconnect_indication (self, reason)
+ *
+ *    Disconnect indication, TSAP disconnected by peer?
+ *
+ */
+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");
+
+	self = ( struct tsap_cb *) instance;
+
+	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);
+}
+
+/*
+ * Function irttp_run_rx_queue (self)
+ *
+ *     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) 
+{
+	struct sk_buff *skb;
+	__u8 *frame;
+	int more = 0;
+	void *instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+
+	instance = self->notify.instance;
+	ASSERT( instance != NULL, return;);
+
+	DEBUG( 4, "irttp_do_events() send=%d,avail=%d,remote=%d\n", 
+	       self->send_credit, self->avail_credit, self->remote_credit);
+
+	if ( irda_lock( &self->rx_queue_lock) == FALSE)
+		return;
+	
+	/*
+	 *  Process receive queue
+	 */
+	while (( !skb_queue_empty( &self->rx_queue)) &&  !self->rx_sdu_busy) {
+
+		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" : 
+		       "FALSE");
+
+		/* Remove TTP header */
+		skb_pull( skb, TTP_HEADER);
+
+		/* Add the length of the remaining data */
+		self->rx_sdu_size += skb->len;
+
+		/*  
+		 * If SAR is disabled, or user has requested no reassembly
+		 * of received fragements then we just deliver them
+		 * immediately. This can be requested by clients that
+		 * 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->rx_sdu_size = 0;
+
+			continue;
+		}
+
+		/* Check if this is a fragment, and not the last fragment */
+		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__ 
+				       "(), queueing fragment\n");
+
+				skb_queue_tail( &self->rx_fragments, skb);
+			} else {
+				DEBUG( 0, __FUNCTION__ "(), Error!\n");
+			}
+		} else {
+			/*
+			 *  This is the last fragment, so time to reassemble!
+			 */
+			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)) {
+
+					DEBUG( 4, __FUNCTION__ 
+					       "(), queueing fragment\n");
+					skb_queue_tail( &self->rx_fragments, 
+							skb);
+
+					skb = irttp_reassemble_skb( self);
+				}
+				self->notify.data_indication( instance, self, 
+							      skb);
+			} else {
+				DEBUG( 0, __FUNCTION__ 
+				       "(), Truncated frame\n");
+				self->notify.data_indication( 
+					self->notify.instance, self, skb);
+			}
+			self->rx_sdu_size = 0;
+		}
+	}
+	/* Reset lock */
+	self->rx_queue_lock = 0;
+}
+
+/*
+ * Function irttp_flush_queues (self)
+ *
+ *     Flushes (removes all frames) in transitt-buffer (tx_list)
+ */
+void irttp_flush_queues( struct tsap_cb *self)
+{
+	struct sk_buff* skb;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	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);
+	}
+	/* 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);
+	}
+	
+}
+
+/*
+ * Function irttp_reasseble (self)
+ *
+ *    Makes a new (continuous) skb of all the fragments in the fragment
+ *    queue
+ *
+ */
+static struct sk_buff *irttp_reassemble_skb( struct tsap_cb *self)
+{
+	struct sk_buff *skb, *frag;
+	int n = 0;  /* Fragment index */
+	int i = 1;  /* Fragment nr */
+
+      	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);
+
+	skb = dev_alloc_skb( self->rx_sdu_size);
+	if ( !skb) {
+		DEBUG( 0, __FUNCTION__ "(), unable to allocate skb\n");
+		return NULL;
+	}
+
+	skb_put( skb, self->rx_sdu_size);
+
+	/*
+	 *  Copy all fragments to a new buffer
+	 */
+	while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) {
+		DEBUG( 4, __FUNCTION__ "(), copying fragment %d with len=%d\n",
+		       i++, (int) frag->len);
+		memcpy( skb->data+n, frag->data, frag->len);
+		n += frag->len;
+
+		dev_kfree_skb( frag);
+	}
+	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);
+
+	self->rx_sdu_size = 0;
+
+	return skb;
+}
+
+/*
+ * Function irttp_fragment_skb (skb)
+ *
+ *    Fragments a frame and queues all the fragments for transmission
+ *
+ */
+static void irttp_fragment_skb( struct tsap_cb *self, struct sk_buff *skb)
+{
+	struct sk_buff *frag;
+	__u8 *frame;
+	int i = 0;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	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) {
+		/*
+		 *  Instead of making the last segment, we just
+		 *  queue what is left of the original skb
+		 */
+		if ( skb->len < self->max_seg_size) {
+			DEBUG( 4, __FUNCTION__ 
+			       "(), queuing last segment\n");
+
+			frame = skb_push( skb, TTP_HEADER);
+			frame[0] = 0x00; /* Clear more bit */
+			skb_queue_tail( &self->tx_queue, skb);
+			
+			return;
+		}
+		
+		/* 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");
+			return;
+		}
+
+		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[0] = TTP_MORE;
+		memcpy( frag->data+1, skb->data, self->max_seg_size);
+		
+		/* Hide the copied data from the original skb */
+		skb_pull( skb, self->max_seg_size);
+		
+		/* Queue segment */
+		DEBUG( 4, __FUNCTION__ "(), queuing segment %d with len=%d\n", 
+		       i++, (int) frag->len);
+
+		skb_queue_tail( &self->tx_queue, frag);
+	}
+}
+
+/*
+ * Function irttp_todo_expired (data)
+ *
+ *    Todo timer has expired!
+ *
+ */
+static void irttp_todo_expired( unsigned long data)
+{
+	struct tsap_cb *self = ( struct tsap_cb *) data;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	/* Check that we still exist */
+	if ( !self || self->magic != TTP_TSAP_MAGIC) {
+		return;
+	}
+
+	irttp_run_rx_queue( self);
+	irttp_run_tx_queue( self);
+
+	/*  Give avay some credits to peer?  */
+	if (( 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);
+	}
+	
+	/* Rearm! */
+	/* irttp_start_todo_timer( self, 50); */
+}
+
+/*
+ * Function irttp_start_todo_timer (self, timeout)
+ *
+ *    Start todo timer. 
+ *
+ */
+static void irttp_start_todo_timer( struct tsap_cb *self, int timeout)
+{
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
+
+	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);
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irttp_proc_read (buf, start, offset, len, unused)
+ *
+ *    Give some info to the /proc file system
+ */
+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;);
+	
+	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");
+			return len;
+		}
+
+		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", 
+				self->dtsap_sel);
+		len += sprintf( buf+len, "  connected: %s, ",
+				self->connected? "TRUE":"FALSE");
+		len += sprintf( buf+len, "avail credit: %d, ",
+				self->avail_credit);
+		len += sprintf( buf+len, "remote credit: %d, ",
+				self->remote_credit);
+		len += sprintf( buf+len, "send credit: %d\n",
+				self->send_credit);
+		len += sprintf( buf+len, "  tx packets: %d, ",
+				self->stats.tx_packets);
+		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, ",
+				self->tx_sdu_busy? "TRUE":"FALSE");
+		len += sprintf( buf+len, "rx_sdu_busy: %s\n",
+				self->rx_sdu_busy? "TRUE":"FALSE");
+		len += sprintf( buf+len, "  max_seg_size: %d, ",
+				self->max_seg_size);
+		len += sprintf( buf+len, "tx_max_sdu_size: %d, ",
+				self->tx_max_sdu_size);
+		len += sprintf( buf+len, "rx_max_sdu_size: %d\n",
+				self->rx_max_sdu_size);
+
+		len += sprintf( buf+len, "  Used by (%s)\n", 
+				self->notify.name);
+
+		len += sprintf( buf+len, "\n");
+		
+		self = ( struct tsap_cb *) hashbin_get_next( irttp->tsaps);
+	}
+	restore_flags(flags);
+
+	return len;
+}
+
+#endif /* PROC_FS */
diff -u --recursive --new-file v2.1.131/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.1.131/linux/net/irda/qos.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/qos.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,448 @@
+/*********************************************************************
+ *                
+ * Filename:      qos.c
+ * Version:       0.1
+ * 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 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/config.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/qos.h>
+#include <net/irda/irlap.h>
+#ifdef CONFIG_IRDA_COMPRESSION
+#include <net/irda/irlap_comp.h>
+#include "../../drivers/net/zlib.h"
+
+#define CI_BZIP2  27 /* Random pick */
+#endif
+
+int min_turn_time[] = { 10000, 5000, 1000, 500, 100, 50, 10, 0 };
+int baud_rates[] = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 1152000,
+		     4000000 };
+int data_size[]  = { 64, 128, 256, 512, 1024, 2048 };
+int add_bofs[]   = { 48, 24, 12, 5, 3, 2, 1, 0 };
+int max_turn_time[] = { 500, 250, 100, 50 };
+int link_disc_time[] = { 3, 8, 12, 16, 20, 25, 30, 40 };
+
+#ifdef CONFIG_IRDA_COMPRESSION
+int compression[] = { CI_BZIP2, CI_DEFLATE, CI_DEFLATE_DRAFT };
+#endif
+/*
+ * Function irda_qos_compute_intersection (qos, new)
+ *
+ *    Compute the intersection of the old QoS capabilites with new ones
+ *
+ */
+void irda_qos_compute_intersection( struct qos_info *qos, struct qos_info *new)
+{
+	ASSERT( qos != NULL, return;);
+	ASSERT( new != NULL, return;);
+
+	/* Apply */
+	qos->baud_rate.bits       &= new->baud_rate.bits;
+	qos->window_size.bits     &= new->window_size.bits;
+	qos->min_turn_time.bits   &= new->min_turn_time.bits;
+	qos->max_turn_time.bits   &= new->max_turn_time.bits;
+	qos->data_size.bits       &= new->data_size.bits;
+	qos->link_disc_time.bits  &= new->link_disc_time.bits;
+	qos->additional_bofs.bits &= new->additional_bofs.bits;
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	qos->compression.bits     &= new->compression.bits;
+#endif
+
+	irda_qos_bits_to_value( qos);
+}
+
+/*
+ * Function irda_init_max_qos_capabilies (qos)
+ *
+ *    The purpose of this function is for layers and drivers to be able to
+ *    set the maximum QoS possible and then "and in" their own limitations
+ * 
+ */
+void irda_init_max_qos_capabilies( struct qos_info *qos)
+{
+	/* 
+	 *  These are the maximum supported values as specified on pages
+	 *  39-43 in IrLAP
+	 */
+
+	/* LSB is first byte, MSB is second byte */
+	qos->baud_rate.bits     = 0x01ff; 
+
+	qos->window_size.bits     = 0x7f;
+	qos->min_turn_time.bits   = 0xff;
+	qos->max_turn_time.bits   = 0x0f;
+	qos->data_size.bits       = 0x3f;
+	qos->link_disc_time.bits  = 0xff;
+	qos->additional_bofs.bits = 0xff;
+
+#ifdef CONFIG_IRDA_COMPRESSION	
+	qos->compression.bits     = 0x03;
+#endif
+}
+
+/*
+ * Function irlap_negotiate (qos_device, qos_session, skb)
+ *
+ *    Negotiate QoS values, not really that much negotiation :-)
+ *    We just set the QoS capabilities for the peer station
+ *
+ */
+void irda_qos_negotiate( struct qos_info *qos_rx, struct qos_info *qos_tx, 
+			 struct sk_buff *skb) 
+{
+	int n=0;
+#ifdef CONFIG_IRDA_COMPRESSION
+	int comp_seen = FALSE;
+#endif
+	__u8 length;
+	__u8 *frame;
+	__u8 final_byte;
+	__u8 code;
+	__u8 byte;
+ 	__u16 final_word;
+	__u16_host_order word;
+
+	ASSERT( qos_tx != NULL, return;);
+	ASSERT( qos_rx != NULL, return;);
+	ASSERT( skb != NULL, return;);
+
+	frame = skb->data;
+
+	while( n < skb->len-2) {
+		code = frame[n++];
+		/* Length */
+		length = frame[n++];
+
+		/*  
+		 *  Get the value, since baud_rate may need two bytes, we
+		 *  Just use word size all the time
+		 */
+		switch( length) {
+		case 1:
+			byte = frame[n++];
+			word.word = byte; /* To make things a little easier */
+			break;
+		case 2:
+#ifdef __LITTLE_ENDIAN
+			word.byte[0] = frame[n++];
+			word.byte[1] = frame[n++];
+#else ifdef __BIG_ENDIAN
+			word.byte[1] = frame[n++];
+			word.byte[0] = frame[n++];
+#endif
+			byte = 0;
+			break;
+		default:
+			DEBUG( 0, __FUNCTION__ "Error\n");
+			word.word = byte = 0;
+			n += length;
+			
+			break;
+		}
+
+		switch( code) {
+		case PI_BAUD_RATE:
+			/* 
+			 *  Stations must agree on baud rate, so calculate
+                         *  intersection 
+			 */
+			DEBUG( 4, "Requested BAUD_RATE: 0x%04x\n", word.word);
+			final_word = word.word & qos_rx->baud_rate.bits;
+			DEBUG( 4, "Final BAUD_RATE: 0x%04x\n", final_word);
+			qos_tx->baud_rate.bits = final_word;
+			qos_rx->baud_rate.bits = final_word;
+			break;
+		case PI_MAX_TURN_TIME:
+			/*
+			 *  Negotiated independently for each station
+			 */
+			DEBUG( 4, "MAX_TURN_TIME: %02x\n", byte);
+			qos_tx->max_turn_time.bits = byte;
+			break;
+		case PI_DATA_SIZE:
+			/*
+			 *  Negotiated independently for each station
+			 */
+			DEBUG( 4, "DATA_SIZE: %02x\n", byte);
+			qos_tx->data_size.bits = byte;
+			break;
+		case PI_WINDOW_SIZE:
+			/*
+			 *  Negotiated independently for each station
+			 */
+			qos_tx->window_size.bits = byte;
+			break;
+		case PI_ADD_BOFS:
+			/*
+			 *  Negotiated independently for each station
+			 */
+			DEBUG( 4, "ADD_BOFS: %02x\n", byte);
+			qos_tx->additional_bofs.bits = byte;	
+			break;
+		case PI_MIN_TURN_TIME:
+			DEBUG( 4, "MIN_TURN_TIME: %02x\n", byte);
+			qos_tx->min_turn_time.bits = byte;
+			break;
+		case PI_LINK_DISC:
+			/*  
+			 *  Stations must agree on link disconnect/threshold 
+			 *  time.
+			 */
+			DEBUG( 4, "LINK_DISC: %02x\n", byte);
+			
+			final_byte = byte & qos_rx->link_disc_time.bits;
+			DEBUG( 4, "Final LINK_DISC: %02x\n", final_byte);
+			qos_tx->link_disc_time.bits = final_byte;
+			qos_rx->link_disc_time.bits = final_byte;
+			break;
+#ifdef CONFIG_IRDA_COMPRESSION
+		case PI_COMPRESSION:
+			final_byte = byte & qos_rx->compression.bits;
+			qos_rx->compression.bits = byte;
+			qos_tx->compression.bits = byte;
+			comp_seen = TRUE;
+			break;
+#endif
+		default:
+			DEBUG( 0, __FUNCTION__ "(), Unknown value\n");
+			break;
+		}
+	}
+#ifdef CONFIG_IRDA_COMPRESSION
+	if ( !comp_seen) {
+		DEBUG( 4, __FUNCTION__ "(), Compression not seen!\n");
+		qos_tx->compression.bits = 0x00;
+		qos_rx->compression.bits = 0x00;
+	}
+#endif
+	/* Convert the negotiated bits to values */
+	irda_qos_bits_to_value( qos_tx);
+	irda_qos_bits_to_value( qos_rx);
+		
+	DEBUG( 4, "Setting BAUD_RATE to %d bps.\n", 
+	       qos_tx->baud_rate.value);
+	DEBUG( 4, "Setting DATA_SIZE to %d bytes\n",
+	       qos_tx->data_size.value);
+	DEBUG( 4, "Setting WINDOW_SIZE to %d\n", 
+	       qos_tx->window_size.value);
+	DEBUG( 4, "Setting XBOFS to %d\n", 
+	       qos_tx->additional_bofs.value);
+	DEBUG( 4, "Setting MAX_TURN_TIME to %d ms.\n",
+	       qos_tx->max_turn_time.value);
+	DEBUG( 4, "Setting MIN_TURN_TIME to %d usecs.\n",
+	       qos_tx->min_turn_time.value);
+	DEBUG( 4, "Setting LINK_DISC to %d secs.\n", 
+	       qos_tx->link_disc_time.value);
+#ifdef CONFIG_IRDA_COMPRESSION
+	DEBUG( 4, "Setting COMPRESSION to %d\n", 
+	       qos_tx->compression.value);
+#endif
+	
+}
+
+/*
+ * Function irlap_insert_negotiation_params (qos, fp)
+ *
+ *    Insert QoS negotiaion pararameters into frame
+ *
+ */
+int irda_insert_qos_negotiation_params( struct qos_info *qos, __u8 *frame)
+{
+	int n;
+	__u16_host_order word;
+
+	ASSERT( qos != NULL, return 0;);
+	ASSERT( frame != NULL, return 0;);
+
+	n = 0;
+
+	/* Set baud rate */
+	if (qos->baud_rate.bits < 256) {
+		frame[n++] = PI_BAUD_RATE;
+		frame[n++] = 0x01;   /* length 1 */
+		frame[n++] = qos->baud_rate.bits;
+	} else {
+		frame[n++] = PI_BAUD_RATE;
+		frame[n++] = 0x02;   /* length 2 */
+		
+		/* 
+		 *  qos->baud_rate.bits is in host byte order, so make sure
+		 *  we transmit it in little endian format 
+		 */
+		word.word = qos->baud_rate.bits;
+#ifdef __LITTLE_ENDIAN
+		frame[n++] = word.byte[0]; /* LSB */
+		frame[n++] = word.byte[1]; /* MSB */
+#else ifdef __BIG_ENDIAN
+		frame[n++] = word.byte[1]; /* LSB */
+		frame[n++] = word.byte[0]; /* MSB */
+#endif
+	}
+
+	/* Set Maximum Turn Around Time */
+	frame[n++] = PI_MAX_TURN_TIME;
+	frame[n++] = 0x01;   /* length 1 */
+	frame[n++] = qos->max_turn_time.bits;
+	
+	/* Set data size */
+	frame[n++] = PI_DATA_SIZE;
+	frame[n++] = 0x01;   /* length 1 */
+	frame[n++] = qos->data_size.bits;
+
+	/* Set window size */
+	frame[n++] = PI_WINDOW_SIZE;
+	frame[n++] = 0x01;   /* length 1 */
+	frame[n++] = qos->window_size.bits;
+
+	/* Set additional BOFs */
+	frame[n++] = PI_ADD_BOFS;
+	frame[n++] = 0x01;   /* length 1 */
+	frame[n++] = qos->additional_bofs.bits;
+
+	/* Set minimum turn around time */
+	frame[n++] = PI_MIN_TURN_TIME;
+	frame[n++] = 0x01;   /* length 1 */
+	frame[n++] = qos->min_turn_time.bits;
+
+	/* Set Link Disconnect/Threshold Time */
+	frame[n++] = PI_LINK_DISC;
+	frame[n++] = 0x01;   /* length 1 */
+	frame[n++] = qos->link_disc_time.bits;
+#ifdef CONFIG_IRDA_COMPRESSION
+	/* Set compression bits*/
+	if ( qos->compression.bits) {
+		DEBUG( 4, __FUNCTION__ "(), inserting compresion bits\n");
+		frame[n++] = PI_COMPRESSION;
+		frame[n++] = 0x01;   /* length 1 */
+		frame[n++] = qos->compression.bits;
+	}
+#endif
+	return n;
+}
+
+int byte_value( __u8 byte, int *array) 
+{
+	int index;
+
+	ASSERT( array != NULL, return -1;);
+
+	index = msb_index( byte);
+	return index_value( index, array);
+}
+
+
+/* __u8 value_byte( int value, int *array) */
+/* { */
+/* 	int index; */
+/* 	__u8 byte; */
+
+/* 	index = value_index( value, array); */
+
+/* 	byte =  */
+/* } */
+
+/*
+ * Function msb_index (word)
+ *
+ *    Returns index to most significant bit (MSB) in word
+ *
+ */
+int msb_index ( __u16 word) 
+{
+	__u16 msb = 0x8000;
+	int index = 15;   /* Current MSB */
+	
+	while( msb) {
+		if ( word & msb)
+			break;   /* Found it! */
+		msb >>=1;
+		index--;
+	}
+
+	return index;
+}
+
+/*
+ * Function value_index (value, array)
+ *
+ *    Returns the index to the value in the specified array
+ */
+int value_index( int value, int *array) 
+{
+	int i;
+	
+	for( i=0;i<8;i++)
+		if ( array[i] == value)
+			break;
+	return i;
+}
+
+/*
+ * Function index_value (index, array)
+ *
+ *    Returns value to index in array, easy!
+ *
+ */
+int index_value( int index, int *array) 
+{
+	return array[index];
+}
+
+void irda_qos_bits_to_value( struct qos_info *qos)
+{
+	int index;
+
+	ASSERT( qos != NULL, return;);
+	
+	index = msb_index( qos->baud_rate.bits);
+	qos->baud_rate.value = baud_rates[index];
+
+	index = msb_index( qos->data_size.bits);
+	qos->data_size.value = data_size[index];
+
+	index = msb_index( qos->window_size.bits);
+	qos->window_size.value = index+1;
+
+	index = msb_index( qos->min_turn_time.bits);
+	qos->min_turn_time.value = min_turn_time[index];
+	
+	index = msb_index( qos->max_turn_time.bits);
+	qos->max_turn_time.value = max_turn_time[index];
+
+	index = msb_index( qos->link_disc_time.bits);
+	qos->link_disc_time.value = link_disc_time[index];
+	
+	index = msb_index( qos->additional_bofs.bits);
+	qos->additional_bofs.value = add_bofs[index];
+
+#ifdef CONFIG_IRDA_COMPRESSION
+	index = msb_index( qos->compression.bits);
+	if ( index >= 0)
+		qos->compression.value = compression[index];
+	else 
+		qos->compression.value = 0;
+#endif
+}
+
diff -u --recursive --new-file v2.1.131/linux/net/irda/timer.c linux/net/irda/timer.c
--- v2.1.131/linux/net/irda/timer.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/timer.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,216 @@
+/*********************************************************************
+ *                
+ * Filename:      timer.c
+ * Version:       
+ * Description:   
+ * 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 by:   Dag Brattli <dagb@cs.uit.no>
+ * 
+ *     Copyright (c) 1997 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 <asm/system.h>
+#include <linux/delay.h>
+
+#include <net/irda/timer.h>
+#include <net/irda/irda.h>
+#include <net/irda/irtty.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp_event.h>
+
+static void irlap_slot_timer_expired( unsigned long data);
+static void irlap_query_timer_expired( unsigned long data);
+static void irlap_final_timer_expired( unsigned long data);
+static void irlap_wd_timer_expired( unsigned long data);
+static void irlap_backoff_timer_expired( unsigned long data);
+
+static void irda_device_media_busy_expired( unsigned long data); 
+/*
+ * Function irda_start_timer (timer, timeout)
+ *
+ *    Start an IrDA timer
+ *
+ */
+void irda_start_timer( struct timer_list *ptimer, int timeout, int data,
+		       TIMER_CALLBACK callback) 
+{
+	del_timer( ptimer);
+ 
+	ptimer->data = (unsigned long) data;
+	ptimer->function = callback;
+	ptimer->expires = jiffies + timeout;
+	
+	add_timer( ptimer);
+}
+
+inline void irlap_start_slot_timer( struct irlap_cb *self, int timeout)
+{
+	irda_start_timer( &self->slot_timer, timeout, (unsigned long) self, 
+			  irlap_slot_timer_expired);
+}
+
+inline void irlap_start_query_timer( struct irlap_cb *self, int timeout)
+{
+	irda_start_timer( &self->query_timer, timeout, (unsigned long) self, 
+			  irlap_query_timer_expired);
+}
+
+inline void irlap_start_final_timer( struct irlap_cb *self, int timeout)
+{
+	irda_start_timer( &self->final_timer, timeout,  (unsigned long) self, 
+			  irlap_final_timer_expired);
+}
+
+inline void irlap_start_wd_timer( struct irlap_cb *self, int timeout)
+{
+	irda_start_timer( &self->wd_timer, timeout, (unsigned long) self, 
+			  irlap_wd_timer_expired);
+}
+
+inline void irlap_start_backoff_timer( struct irlap_cb *self, int timeout)
+{
+	irda_start_timer( &self->backoff_timer, timeout, (unsigned long) self, 
+			  irlap_backoff_timer_expired);
+}
+
+inline void irda_device_start_mbusy_timer( struct irda_device *self) 
+{
+	irda_start_timer( &self->media_busy_timer, MEDIABUSY_TIMEOUT, 
+			  (unsigned long) self, 
+			  irda_device_media_busy_expired);
+	
+}
+
+inline void irlmp_start_watchdog_timer( struct lsap_cb *self, int timeout) 
+{
+	irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self,
+			  irlmp_watchdog_timer_expired);
+}
+
+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);
+}
+
+/*
+ * Function irlap_slot_timer_expired (data)
+ *
+ *    IrLAP slot timer has expired
+ *
+ */
+static void irlap_slot_timer_expired( unsigned long data)
+{
+	struct irlap_cb *self = (struct irlap_cb *) data;
+
+	DEBUG( 4, "Slot timer expired!\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_do_event( self, SLOT_TIMER_EXPIRED, NULL, NULL);
+} 
+
+/*
+ * Function irlap_query_timer_expired (data)
+ *
+ *    IrLAP query timer has expired
+ *
+ */
+static void irlap_query_timer_expired( unsigned long data)
+{
+	struct irlap_cb *self = (struct irlap_cb *) data;
+
+	DEBUG( 4, "Query timer expired!\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_do_event( self, QUERY_TIMER_EXPIRED, NULL, NULL);
+} 
+
+/*
+ * Function irda_final_timer_expired (data)
+ *
+ *    
+ *
+ */
+static void irlap_final_timer_expired( unsigned long data)
+{
+	struct irlap_cb *self = (struct irlap_cb *) data;
+
+	DEBUG( 4, "Final timer expired!\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+
+	irlap_do_event( self, FINAL_TIMER_EXPIRED, NULL, NULL);
+}
+
+/*
+ * Function irda_wd_timer_expired (data)
+ *
+ *    
+ *
+ */
+static void irlap_wd_timer_expired( unsigned long data)
+{
+	struct irlap_cb *self = (struct irlap_cb *) data;
+	
+	DEBUG( 4, "WD timer expired!\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	
+	irlap_do_event( self, WD_TIMER_EXPIRED, NULL, NULL);
+}
+
+/*
+ * Function irda_backoff_timer_expired (data)
+ *
+ *    
+ *
+ */
+static void irlap_backoff_timer_expired( unsigned long data)
+{
+	struct irlap_cb *self = (struct irlap_cb *) data;
+	
+	DEBUG( 0, "Backoff timer expired!\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == LAP_MAGIC, return;);
+	
+	irlap_do_event( self, BACKOFF_TIMER_EXPIRED, NULL, NULL);
+}
+
+
+/*
+ * Function irtty_media_busy_expired (data)
+ *
+ *    
+ */
+void irda_device_media_busy_expired( unsigned long data) 
+{
+	struct irda_device *self = ( struct irda_device *) data;
+
+	DEBUG( 4, "Mediabusy timer expired!\n");
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRDA_DEVICE_MAGIC, return;);
+
+	irda_device_set_media_busy( self, FALSE);
+}
diff -u --recursive --new-file v2.1.131/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.1.131/linux/net/irda/wrapper.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/wrapper.c	Thu Dec 17 09:01:03 1998
@@ -0,0 +1,318 @@
+/*********************************************************************
+ *                
+ * Filename:      wrapper.c
+ * Version:       
+ * Description:   IrDA Wrapper layer
+ * Status:        Experimental.
+ * Author:        Dag Brattli <dagb@cs.uit.no>
+ * Created at:    Mon Aug  4 20:40:53 1997
+ * Modified at:   Wed Dec  9 01:35:53 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 <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irtty.h>
+#include <net/irda/crc.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#define MIN_LENGTH 14
+
+__inline__ static int stuff_byte( __u8 byte, __u8 *buf);
+
+/*
+ * Function async_wrap (skb, *tx_buff)
+ *
+ *    Makes a new buffer with wrapping and stuffing, should check that 
+ *    we don't get tx buffer overflow.
+ */
+int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize)
+{
+	__u8 byte;
+	int i, n;
+	int xbofs;
+	union {
+		__u16 value;
+		__u8 bytes[2];
+	} fcs;
+
+
+ 	DEBUG( 6, __FUNCTION__ "()\n"); 
+	ASSERT( skb != NULL, return 0;);
+
+	/* Initialize variables */
+	fcs.value = INIT_FCS;
+	n = 0;
+
+	if ( skb->len > 2048) {
+		DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n", 
+		       (int) skb->len);
+
+		return 0;
+	}
+	
+	/*
+	 *  Send  XBOF's for required min. turn time and for the negotiated
+	 *  additional XBOFS
+	 */
+ 	xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
+	for ( i=0; i<xbofs; i++) {
+ 		tx_buff[n++] = XBOF; 
+ 	}
+
+	/* Start of packet character BOF */
+	tx_buff[n++] = BOF;
+
+	/* Insert frame and calc CRC */
+	for( i=0; i < skb->len; i++) {
+		byte = skb->data[i];
+		
+		/*
+		 *  Check for the possibility of tx buffer overflow. We use
+		 *  bufsize-5 since the maximum number of bytes that can be 
+		 *  transmitted after this point is 5.
+		 */
+		if ( n > buffsize-5) {
+			printk( KERN_WARNING 
+				"IrDA Wrapper: TX-buffer overflow!\n");
+			return n;
+		}
+		n+=stuff_byte( byte, tx_buff+n);
+		fcs.value = IR_FCS( fcs.value, byte);
+	}
+	
+	/* Insert CRC in little endian format (LSB first) */
+	fcs.value = ~fcs.value;
+#ifdef __LITTLE_ENDIAN
+	n += stuff_byte( fcs.bytes[0], tx_buff+n);
+	n += stuff_byte( fcs.bytes[1], tx_buff+n);
+#else ifdef __BIG_ENDIAN
+	n += stuff_byte( fcs.bytes[1], tx_buff+n);
+	n += stuff_byte( fcs.bytes[0], tx_buff+n);
+#endif
+	tx_buff[n++] = EOF;
+	
+	DEBUG( 6, "async_wrap() -->\n");
+	
+	return n;
+}
+
+/*
+ * Function async_bump (irdev)
+ *
+ *    Got a frame, make a copy of it, and pass it up the stack!
+ *
+ */
+static __inline__ void async_bump( struct irda_device *irdev, __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");
+		irdev->stats.rx_dropped++;
+		return;
+	}
+
+	/*  Align to 20 bytes */
+	skb_reserve( skb, 1);
+	
+	/* For finding out how much time we use to
+	   send a frame */
+	do_gettimeofday( &skb->stamp);
+
+	ASSERT( len-2 > 0, return;);
+
+        /* Copy data without CRC */
+	skb_put( skb, len-2);
+	memcpy( skb->data, buf, len-2); 
+	
+	irdev->rx_buff.len = 0;
+	/* 
+	 *  Feed it to IrLAP layer 
+	 */
+	/* memcpy(skb_put(skb,count), ax->rbuff, count); */
+	skb->dev = &irdev->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+
+	netif_rx( skb);
+	irdev->stats.rx_packets++;
+	
+        /* irlap_input( skb, skb->dev, NULL); */
+}
+ 
+/*
+ * Function async_unwrap (skb)
+ *
+ *    Parse and de-stuff frame received from the IR-port
+ *
+ */
+void async_unwrap_char( struct irda_device *irdev, __u8 byte) 
+{
+	DEBUG( 6, "async_unwrap()\n");
+
+	/* State machine for receiving frames */	   
+	switch( irdev->rx_buff.state) {
+	case OUTSIDE_FRAME:
+		if ( byte == BOF) {
+			irdev->rx_buff.state = BEGIN_FRAME;
+			irdev->rx_buff.in_frame = TRUE;
+		} else if ( byte == EOF) {
+			irda_device_set_media_busy( irdev, TRUE);
+		}
+		break;
+	case BEGIN_FRAME:
+		switch ( byte) {
+		case BOF:
+			/* Continue */
+			break;
+		case CE:
+			/* Stuffed byte */
+			irdev->rx_buff.state = LINK_ESCAPE;
+			break;
+		case EOF:
+			/* Abort frame */
+			DEBUG( 0, "Frame abort (1)\n");
+			irdev->rx_buff.state = OUTSIDE_FRAME;
+			break;
+		default:
+			/* Got first byte of frame */
+			if ( irdev->rx_buff.len < irdev->rx_buff.truesize)  {
+				irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+			
+				irdev->rx_buff.fcs = IR_FCS ( INIT_FCS, byte);
+				irdev->rx_buff.state = INSIDE_FRAME;
+			} else 
+				printk( "Rx buffer overflow\n");
+			break;
+		}
+		break;
+	case LINK_ESCAPE:
+		switch ( byte) {
+		case BOF:
+			/* New frame? */
+			DEBUG( 4, "New frame?\n");
+			irdev->rx_buff.state = BEGIN_FRAME;
+			irdev->rx_buff.len = 0;
+			irda_device_set_media_busy( irdev, TRUE);
+			break;
+		case CE:
+			DEBUG( 4, "WARNING: State not defined\n");
+			break;
+		case EOF:
+			/* Abort frame */
+			DEBUG( 0, "Abort frame (2)\n");
+			irdev->rx_buff.state = OUTSIDE_FRAME;
+			irdev->rx_buff.len = 0;
+			break;
+		default:
+			/* 
+			 *  Stuffed char, complement bit 5 of byte 
+			 *  following CE, IrLAP p.114 
+			 */
+			byte ^= IR_TRANS;
+			if ( irdev->rx_buff.len < irdev->rx_buff.truesize)  {
+				irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+			
+				irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte);
+				irdev->rx_buff.state = INSIDE_FRAME;
+			} else 
+				printk( "Rx buffer overflow\n");
+			break;
+		}
+		break;
+	case INSIDE_FRAME:
+		switch ( byte) {
+		case BOF:
+			/* New frame? */
+			DEBUG( 4, "New frame?\n");
+			irdev->rx_buff.state = BEGIN_FRAME;
+			irdev->rx_buff.len = 0;
+			irda_device_set_media_busy( irdev, TRUE);
+			break;
+		case CE:
+			/* Stuffed char */
+			irdev->rx_buff.state = LINK_ESCAPE;
+			break;
+		case EOF:
+			/* End of frame */
+			irdev->rx_buff.state = OUTSIDE_FRAME;
+			irdev->rx_buff.in_frame = FALSE;
+			
+			/* 
+			 *  Test FCS and deliver frame if it's good
+			 */			
+			if ( irdev->rx_buff.fcs == GOOD_FCS) {
+				async_bump( irdev, irdev->rx_buff.data, 
+					    irdev->rx_buff.len);
+			} else {
+				/* 
+				 *  Wrong CRC, discard frame! 
+				 */
+				DEBUG( 0, "Received frame has wrong CRC\n");
+				irda_device_set_media_busy( irdev, TRUE); 
+				irdev->rx_buff.len = 0;
+			}			
+			break;
+		default:
+			/* Next byte of frame */
+			if ( irdev->rx_buff.len < irdev->rx_buff.truesize)  {
+				irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+				
+				irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte);
+			} else 
+				printk( "Rx buffer overflow\n");
+			break;
+		}
+		break;
+	}
+}
+ 
+/*
+ * Function stuff_byte (byte, buf)
+ *
+ *    Byte stuff one single byte and put the result in buffer pointed to by
+ *    buf. The buffer must at all times be able to have two bytes inserted.
+ * 
+ */
+__inline__ static int stuff_byte( __u8 byte, __u8 *buf) 
+{
+	switch ( byte) {
+	case BOF:
+	case EOF:
+	case CE:
+		/* Insert transparently coded */
+		buf[0] = CE;               /* Send link escape */
+		buf[1] = byte^IR_TRANS;    /* Complement bit 5 */
+		return 2;
+		/* break; */
+	default:
+		 /* Non-special value, no transparency required */
+		buf[0] = byte;
+		return 1;
+		/* break; */
+	}
+}
+	 
+
diff -u --recursive --new-file v2.1.131/linux/net/protocols.c linux/net/protocols.c
--- v2.1.131/linux/net/protocols.c	Sun Nov  8 14:03:15 1998
+++ linux/net/protocols.c	Thu Dec 17 09:03:57 1998
@@ -57,6 +57,10 @@
 #endif
 #endif
 
+#ifdef CONFIG_IRDA
+#include <net/irda/irdacall.h>
+#endif
+
 #if defined(CONFIG_DECNET)
 #include <net/decnet_call.h>
 #endif
@@ -159,6 +163,10 @@
 
 #ifdef CONFIG_ECONET
   { "Econet",	econet_proto_init },			/* Acorn Econet */
+#endif
+
+#ifdef CONFIG_IRDA
+  { "IrDA",     irda_proto_init },                     /* IrDA protocols */
 #endif
 
   { NULL,	NULL		}			/* End marker			*/
diff -u --recursive --new-file v2.1.131/linux/net/rose/rose_dev.c linux/net/rose/rose_dev.c
--- v2.1.131/linux/net/rose/rose_dev.c	Tue Apr 14 14:29:27 1998
+++ linux/net/rose/rose_dev.c	Thu Dec 17 09:07:45 1998
@@ -56,6 +56,7 @@
 {
 	struct net_device_stats *stats = (struct net_device_stats *)dev->priv;
 
+#ifdef CONFIG_INET
 	if (!dev->start) {
 		stats->rx_errors++;
 		return 0;
@@ -73,7 +74,9 @@
 	skb->pkt_type = PACKET_HOST;
 
 	ip_rcv(skb, skb->dev, NULL);
-
+#else
+	kfree_skb(skb);
+#endif
 	return 1;
 }
 
@@ -101,11 +104,8 @@
 	unsigned char *bp = (unsigned char *)skb->data;
 	struct sk_buff *skbn;
 
+#ifdef CONFIG_INET
 	if (arp_find(bp + 7, skb)) {
-#if 0
-		/* BUGGGG! If arp_find returned 1, skb does not exist. --ANK*/
-		kfree_skb(skb);
-#endif
 		return 1;
 	}
 
@@ -126,7 +126,7 @@
 
 	stats->tx_packets++;
 	stats->tx_bytes += skbn->len;
-
+#endif
 	return 1;
 }
 
diff -u --recursive --new-file v2.1.131/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c
--- v2.1.131/linux/net/wanrouter/wanmain.c	Sat Sep  5 16:46:42 1998
+++ linux/net/wanrouter/wanmain.c	Tue Dec 22 08:22:07 1998
@@ -25,6 +25,8 @@
 * Oct 15, 1997  Farhan Thawar   changed wan_encapsulate to add a pad byte of 0
 * Apr 20, 1998	Alan Cox	Fixed 2.1 symbols
 * May 17, 1998  K. Baranowski	Fixed SNAP encapsulation in wan_encapsulate
+* Dec 15, 1998  Arnaldo Melo    support for firmwares of up to 128000 bytes
+*                               check wandev->setup return value
 *****************************************************************************/
 
 #include <linux/stddef.h>	/* offsetof(), etc. */
@@ -459,7 +461,7 @@
 
 	if (conf->data_size && conf->data)
 	{
-		if(conf->data_size > 64000 || conf->data_size < 0){
+		if(conf->data_size > 128000 || conf->data_size < 0){
 			goto bail;
 		}
 		data = kmalloc(conf->data_size, GFP_KERNEL);
@@ -468,8 +470,7 @@
 			if(!copy_from_user(data, conf->data, conf->data_size))
 			{
 				conf->data=data;
-				wandev->setup(wandev,conf);
-				err = 0;
+				err = wandev->setup(wandev,conf);
 			}
 			else 
 				err = -ENOBUFS;
@@ -689,12 +690,10 @@
 	return 0;
 }
 
-#ifdef MODULE
 EXPORT_SYMBOL(register_wan_device);
 EXPORT_SYMBOL(unregister_wan_device);
 EXPORT_SYMBOL(wanrouter_encapsulate);
 EXPORT_SYMBOL(wanrouter_type_trans);
-#endif
 
 /*
  *	End
diff -u --recursive --new-file v2.1.131/linux/scripts/checkhelp.pl linux/scripts/checkhelp.pl
--- v2.1.131/linux/scripts/checkhelp.pl	Wed Dec 31 16:00:00 1969
+++ linux/scripts/checkhelp.pl	Thu Dec 17 09:07:46 1998
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+# checkhelp.pl - finds configuration options that have no
+#                corresponding section in the help file
+#
+# made by Meelis Roos (mroos@tartu.cyber.ee)
+
+# read the help file
+@options=split /\n/, `grep '^CONFIG' Documentation/Configure.help`;
+die "Can't read Documentation/Configure.help\n" if $#options == -1;
+
+#read all the files
+foreach $file (@ARGV)
+{
+	open (FILE, $file) || die "Can't open $file: $!\n";
+	while (<FILE>) {
+		# repeat until no CONFIG_* are left
+		while (/^\s*(bool|tristate|dep_tristate|string|int|hex).*' *(.*)'.*(CONFIG_\w*)/) {
+			$what=$3;
+			$name=$2;
+			s/$3//;
+			@found = grep (/$what$/, @options);
+			if ($#found == -1) {
+				next if $nohelp{$what};
+				print "$name\n$what\n  No help for $what\n\n";
+				$nohelp{$what}=1;
+			}
+		}
+	}
+	close (FILE);
+}
diff -u --recursive --new-file v2.1.131/linux/scripts/mkdep.c linux/scripts/mkdep.c
--- v2.1.131/linux/scripts/mkdep.c	Wed Dec 16 10:32:56 1998
+++ linux/scripts/mkdep.c	Fri Dec 18 14:01:48 1998
@@ -226,8 +226,8 @@
  */
 #define MAX2(a,b) ((a)>(b)?(a):(b))
 #define MIN2(a,b) ((a)<(b)?(a):(b))
-#define MAX5(a,b,c,d,e) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,e)))))
-#define MIN5(a,b,c,d,e) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,e)))))
+#define MAX6(a,b,c,d,e,f) (MAX2(a,MAX2(b,MAX2(c,MAX2(d,MAX2(e,f))))))
+#define MIN6(a,b,c,d,e,f) (MIN2(a,MIN2(b,MIN2(c,MIN2(d,MIN2(e,f))))))
 
 
 
@@ -241,11 +241,12 @@
  *    m|#\s*include\s*<(.*?>"|
  *    m|#\s*(?define|undef)\s*CONFIG_(\w*)|
  *    m|(?!\w)CONFIG_|
+ *    m|__SMP__|
  *
  * About 98% of the CPU time is spent here, and most of that is in
  * the 'start' paragraph.  Because the current characters are
  * in a register, the start loop usually eats 4 or 8 characters
- * per memory read.  The MAX5 and MIN5 tests dispose of most
+ * per memory read.  The MAX6 and MIN6 tests dispose of most
  * input characters with 1 or 2 comparisons.
  */
 void state_machine(const char * map)
@@ -258,13 +259,14 @@
 start:
 	GETNEXT
 __start:
-	if (current > MAX5('/','\'','"','#','C')) goto start;
-	if (current < MIN5('/','\'','"','#','C')) goto start;
+	if (current > MAX6('/','\'','"','#','C','_')) goto start;
+	if (current < MIN6('/','\'','"','#','C','_')) goto start;
 	CASE('/',  slash);
 	CASE('\'', squote);
 	CASE('"',  dquote);
 	CASE('#',  pound);
 	CASE('C',  cee);
+	CASE('_',  underscore);
 	goto start;
 
 /* / */
@@ -398,6 +400,18 @@
 		goto cee_CONFIG_word;
 	use_config(map_dot, next - map_dot - 1);
 	goto __start;
+
+/* __SMP__ */
+underscore:
+	GETNEXT NOTCASE('_', __start);
+	GETNEXT NOTCASE('S', __start);
+	GETNEXT NOTCASE('M', __start);
+	GETNEXT NOTCASE('P', __start);
+	GETNEXT NOTCASE('_', __start);
+	GETNEXT NOTCASE('_', __start);
+	use_config("SMP", 3);
+	goto __start;
+
     }
 }
 
